Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop
This commit is contained in:
@@ -73,7 +73,7 @@ body:
|
|||||||
label: Version
|
label: Version
|
||||||
description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu.
|
description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu.
|
||||||
options:
|
options:
|
||||||
- v1.1.19.3 (Treacherous Tides Hotfix 2)
|
- v1.2.6.0 (Winter Update)
|
||||||
- Other
|
- Other
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class Camera : IDisposable
|
class Camera
|
||||||
{
|
{
|
||||||
public static bool FollowSub = true;
|
public static bool FollowSub = true;
|
||||||
|
|
||||||
@@ -147,21 +147,10 @@ namespace Barotrauma
|
|||||||
position = Vector2.Zero;
|
position = Vector2.Zero;
|
||||||
|
|
||||||
CreateMatrices();
|
CreateMatrices();
|
||||||
// TODO: this has the potential to cause a resource leak
|
|
||||||
// by sneakily creating a reference to cameras that we might
|
|
||||||
// fail to release.
|
|
||||||
GameMain.Instance.ResolutionChanged += CreateMatrices;
|
|
||||||
|
|
||||||
UpdateTransform(false);
|
UpdateTransform(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool disposed = false;
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!disposed) { GameMain.Instance.ResolutionChanged -= CreateMatrices; }
|
|
||||||
disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 TargetPos { get; set; }
|
public Vector2 TargetPos { get; set; }
|
||||||
|
|
||||||
public Vector2 GetPosition()
|
public Vector2 GetPosition()
|
||||||
@@ -207,6 +196,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void UpdateTransform(bool interpolate = true, bool updateListener = true)
|
public void UpdateTransform(bool interpolate = true, bool updateListener = true)
|
||||||
{
|
{
|
||||||
|
if (GameMain.GraphicsWidth != Resolution.X ||
|
||||||
|
GameMain.GraphicsHeight != Resolution.Y)
|
||||||
|
{
|
||||||
|
CreateMatrices();
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ namespace Barotrauma
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!MathUtils.IsValid(value)) { return; }
|
if (!MathUtils.IsValid(value)) { return; }
|
||||||
|
if (this != Controlled) { return; }
|
||||||
if (Screen.Selected?.Cam != null)
|
if (Screen.Selected?.Cam != null)
|
||||||
{
|
{
|
||||||
Screen.Selected.Cam.Shake = value;
|
Screen.Selected.Cam.Shake = value;
|
||||||
@@ -229,6 +230,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float pressureEffectTimer;
|
||||||
|
|
||||||
private readonly List<ObjectiveEntity> activeObjectiveEntities = new List<ObjectiveEntity>();
|
private readonly List<ObjectiveEntity> activeObjectiveEntities = new List<ObjectiveEntity>();
|
||||||
public IEnumerable<ObjectiveEntity> ActiveObjectiveEntities
|
public IEnumerable<ObjectiveEntity> ActiveObjectiveEntities
|
||||||
{
|
{
|
||||||
@@ -333,18 +336,22 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!IsProtectedFromPressure && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f))
|
if (!IsProtectedFromPressure && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f))
|
||||||
{
|
{
|
||||||
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
|
//wait until the character has been in pressure for one second so the zoom doesn't
|
||||||
if (pressure > 0.0f)
|
//"flicker" in and out if the pressure fluctuates around the minimum threshold
|
||||||
|
pressureEffectTimer += deltaTime;
|
||||||
|
if (pressureEffectTimer > 1.0f)
|
||||||
{
|
{
|
||||||
//lerp in during the 1st second of the pressure timer so the zoom doesn't
|
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
|
||||||
//"flicker" in and out if the pressure fluctuates around the minimum threshold
|
float zoomInEffectStrength = MathHelper.Clamp(pressure / 100.0f, 0.0f, 1.0f);
|
||||||
float timerMultiplier = (PressureTimer / 100.0f);
|
|
||||||
float zoomInEffectStrength = MathHelper.Clamp(pressure / 100.0f * timerMultiplier, 0.0f, 1.0f);
|
|
||||||
cam.Zoom = MathHelper.Lerp(cam.Zoom,
|
cam.Zoom = MathHelper.Lerp(cam.Zoom,
|
||||||
cam.DefaultZoom + (Math.Max(pressure, 10) / 150.0f) * Rand.Range(0.9f, 1.1f),
|
cam.DefaultZoom + (Math.Max(pressure, 10) / 150.0f) * Rand.Range(0.9f, 1.1f),
|
||||||
zoomInEffectStrength);
|
zoomInEffectStrength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pressureEffectTimer = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsHumanoid)
|
if (IsHumanoid)
|
||||||
{
|
{
|
||||||
@@ -521,22 +528,25 @@ namespace Barotrauma
|
|||||||
if (controlled == this)
|
if (controlled == this)
|
||||||
{
|
{
|
||||||
controlled = null;
|
controlled = null;
|
||||||
if (!(Screen.Selected?.Cam is null))
|
if (Screen.Selected?.Cam is not null)
|
||||||
{
|
{
|
||||||
Screen.Selected.Cam.TargetPos = Vector2.Zero;
|
Screen.Selected.Cam.TargetPos = Vector2.Zero;
|
||||||
Lights.LightManager.ViewTarget = null;
|
Lights.LightManager.ViewTarget = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sounds.ForEach(s => s.Sound?.Dispose());
|
||||||
|
sounds.Clear();
|
||||||
|
|
||||||
if (GameMain.GameSession?.CrewManager != null &&
|
if (GameMain.GameSession?.CrewManager != null &&
|
||||||
GameMain.GameSession.CrewManager.GetCharacters().Contains(this))
|
GameMain.GameSession.CrewManager.GetCharacters().Contains(this))
|
||||||
{
|
{
|
||||||
GameMain.GameSession.CrewManager.RemoveCharacter(this);
|
GameMain.GameSession.CrewManager.RemoveCharacter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.Client?.Character == this) GameMain.Client.Character = null;
|
|
||||||
|
|
||||||
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
|
if (GameMain.Client?.Character == this) { GameMain.Client.Character = null; }
|
||||||
|
|
||||||
|
if (Lights.LightManager.ViewTarget == this) { Lights.LightManager.ViewTarget = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -894,7 +894,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); }
|
if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); }
|
||||||
|
|
||||||
Vector2 drawPos = target is Entity ? (target as Entity).DrawPosition :
|
Vector2 drawPos = target is Entity entity ? entity.DrawPosition :
|
||||||
target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition;
|
target.Submarine == null ? target.Position : target.Position + target.Submarine.DrawPosition;
|
||||||
drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
drawPos += Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target];
|
||||||
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha,
|
GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha,
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if ((int)newLevel > (int)prevLevel)
|
if ((int)newLevel > (int)prevLevel)
|
||||||
{
|
{
|
||||||
|
Character.Controlled?.SelectedItem?.OnPlayerSkillsChanged();
|
||||||
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
int increase = Math.Max((int)newLevel - (int)prevLevel, 1);
|
||||||
|
|
||||||
Character?.AddMessage(
|
Character?.AddMessage(
|
||||||
@@ -518,7 +519,7 @@ namespace Barotrauma
|
|||||||
attachment.Sprite.Draw(spriteBatch, drawPos, color ?? Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
attachment.Sprite.Draw(spriteBatch, drawPos, color ?? Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharacterInfo ClientRead(Identifier speciesName, IReadMessage inc)
|
public static CharacterInfo ClientRead(Identifier speciesName, IReadMessage inc, bool requireJobPrefabFound = true)
|
||||||
{
|
{
|
||||||
ushort infoID = inc.ReadUInt16();
|
ushort infoID = inc.ReadUInt16();
|
||||||
string newName = inc.ReadString();
|
string newName = inc.ReadString();
|
||||||
@@ -554,14 +555,19 @@ namespace Barotrauma
|
|||||||
if (jobIdentifier > 0)
|
if (jobIdentifier > 0)
|
||||||
{
|
{
|
||||||
jobPrefab = JobPrefab.Prefabs.Find(jp => jp.UintIdentifier == jobIdentifier);
|
jobPrefab = JobPrefab.Prefabs.Find(jp => jp.UintIdentifier == jobIdentifier);
|
||||||
if (jobPrefab == null)
|
if (jobPrefab == null && requireJobPrefabFound)
|
||||||
{
|
{
|
||||||
throw new Exception($"Error while reading {nameof(CharacterInfo)} received from the server: could not find a job prefab with the identifier \"{jobIdentifier}\".");
|
throw new Exception($"Error while reading {nameof(CharacterInfo)} received from the server: could not find a job prefab with the identifier \"{jobIdentifier}\".");
|
||||||
}
|
}
|
||||||
foreach (SkillPrefab skillPrefab in jobPrefab.Skills.OrderBy(s => s.Identifier))
|
byte skillCount = inc.ReadByte();
|
||||||
|
List<SkillPrefab> jobSkills = jobPrefab?.Skills.OrderBy(s => s.Identifier).ToList();
|
||||||
|
for (int i = 0; i < skillCount; i++)
|
||||||
{
|
{
|
||||||
float skillLevel = inc.ReadSingle();
|
float skillLevel = inc.ReadSingle();
|
||||||
skillLevels.Add(skillPrefab.Identifier, skillLevel);
|
if (jobSkills != null && i < jobSkills.Count)
|
||||||
|
{
|
||||||
|
skillLevels.Add(jobSkills[i].Identifier, skillLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2170,6 +2170,8 @@ namespace Barotrauma
|
|||||||
medUIExtra?.Remove();
|
medUIExtra?.Remove();
|
||||||
medUIExtra = null;
|
medUIExtra = null;
|
||||||
|
|
||||||
|
Character.OnAttacked -= OnAttacked;
|
||||||
|
|
||||||
limbIndicatorOverlay?.Remove();
|
limbIndicatorOverlay?.Remove();
|
||||||
limbIndicatorOverlay = null;
|
limbIndicatorOverlay = null;
|
||||||
|
|
||||||
|
|||||||
@@ -1216,7 +1216,7 @@ namespace Barotrauma
|
|||||||
pos: new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
pos: new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||||
srcRect: w.Sprite.SourceRect,
|
srcRect: w.Sprite.SourceRect,
|
||||||
color: Color.White,
|
color: Color.White,
|
||||||
rotation: rotation,
|
rotationRad: rotation,
|
||||||
origin: origin,
|
origin: origin,
|
||||||
scale: new Vector2(scale, scale),
|
scale: new Vector2(scale, scale),
|
||||||
effects: spriteEffect,
|
effects: spriteEffect,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Barotrauma
|
|||||||
bool allowCheats = GameMain.NetworkMember == null && (GameMain.GameSession?.GameMode is TestGameMode || Screen.Selected is { IsEditor: true });
|
bool allowCheats = GameMain.NetworkMember == null && (GameMain.GameSession?.GameMode is TestGameMode || Screen.Selected is { IsEditor: true });
|
||||||
if (!allowCheats && !CheatsEnabled && IsCheat)
|
if (!allowCheats && !CheatsEnabled && IsCheat)
|
||||||
{
|
{
|
||||||
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + names[0] + "\".", Color.Red);
|
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + Names[0] + "\".", Color.Red);
|
||||||
#if USE_STEAM
|
#if USE_STEAM
|
||||||
NewMessage("Enabling cheats will disable Steam achievements during this play session.", Color.Red);
|
NewMessage("Enabling cheats will disable Steam achievements during this play session.", Color.Red);
|
||||||
#endif
|
#endif
|
||||||
@@ -215,11 +215,11 @@ namespace Barotrauma
|
|||||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsCommandPermitted(string command, GameClient client)
|
private static bool IsCommandPermitted(Identifier command, GameClient client)
|
||||||
{
|
{
|
||||||
if (GameMain.LuaCs.Game.IsCustomCommandPermitted(command)) { return true; }
|
if (GameMain.LuaCs.Game.IsCustomCommandPermitted(command)) { return true; }
|
||||||
|
|
||||||
switch (command)
|
switch (command.Value.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "kick":
|
case "kick":
|
||||||
return client.HasPermission(ClientPermissions.Kick);
|
return client.HasPermission(ClientPermissions.Kick);
|
||||||
@@ -306,7 +306,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
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: GUIStyle.SmallFont, wrap: true)
|
RichString.Rich(msg.Text), textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
TextColor = msg.Color
|
TextColor = msg.Color
|
||||||
@@ -348,7 +348,7 @@ namespace Barotrauma
|
|||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 170, 0), textContainer.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(20, 0) },
|
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 170, 0), textContainer.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(20, 0) },
|
||||||
command.help, textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
|
command.Help, textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
|
||||||
{
|
{
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
TextColor = Color.White
|
TextColor = Color.White
|
||||||
@@ -356,7 +356,7 @@ namespace Barotrauma
|
|||||||
textContainer.RectTransform.NonScaledSize = new Point(textContainer.RectTransform.NonScaledSize.X, textBlock.RectTransform.NonScaledSize.Y + 5);
|
textContainer.RectTransform.NonScaledSize = new Point(textContainer.RectTransform.NonScaledSize.X, textBlock.RectTransform.NonScaledSize.Y + 5);
|
||||||
textBlock.SetTextPos();
|
textBlock.SetTextPos();
|
||||||
new GUITextBlock(new RectTransform(new Point(150, textContainer.Rect.Height), textContainer.RectTransform),
|
new GUITextBlock(new RectTransform(new Point(150, textContainer.Rect.Height), textContainer.RectTransform),
|
||||||
command.names[0], textAlignment: Alignment.TopLeft);
|
command.Names[0].Value, textAlignment: Alignment.TopLeft);
|
||||||
|
|
||||||
listBox.UpdateScrollBarSize();
|
listBox.UpdateScrollBarSize();
|
||||||
listBox.BarScroll = 1.0f;
|
listBox.BarScroll = 1.0f;
|
||||||
@@ -366,7 +366,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static void AssignOnClientExecute(string names, Action<string[]> onClientExecute)
|
private static void AssignOnClientExecute(string names, Action<string[]> onClientExecute)
|
||||||
{
|
{
|
||||||
Command command = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
Command command = commands.Find(c => c.Names.Intersect(names.Split('|').ToIdentifiers()).Any());
|
||||||
if (command == null)
|
if (command == null)
|
||||||
{
|
{
|
||||||
throw new Exception("AssignOnClientExecute failed. Command matching the name(s) \"" + names + "\" not found.");
|
throw new Exception("AssignOnClientExecute failed. Command matching the name(s) \"" + names + "\" not found.");
|
||||||
@@ -380,7 +380,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static void AssignRelayToServer(string names, bool relay)
|
private static void AssignRelayToServer(string names, bool relay)
|
||||||
{
|
{
|
||||||
Command command = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
|
Command command = commands.Find(c => c.Names.Intersect(names.Split('|').ToIdentifiers()).Any());
|
||||||
if (command == null)
|
if (command == null)
|
||||||
{
|
{
|
||||||
DebugConsole.Log("Could not assign to relay to server: " + names);
|
DebugConsole.Log("Could not assign to relay to server: " + names);
|
||||||
@@ -691,6 +691,7 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("savebinds", false);
|
AssignRelayToServer("savebinds", false);
|
||||||
AssignRelayToServer("spreadsheetexport", false);
|
AssignRelayToServer("spreadsheetexport", false);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
AssignRelayToServer("listspamfilters", false);
|
||||||
AssignRelayToServer("crash", false);
|
AssignRelayToServer("crash", false);
|
||||||
AssignRelayToServer("showballastflorasprite", false);
|
AssignRelayToServer("showballastflorasprite", false);
|
||||||
AssignRelayToServer("simulatedlatency", false);
|
AssignRelayToServer("simulatedlatency", false);
|
||||||
@@ -716,6 +717,8 @@ namespace Barotrauma
|
|||||||
AssignRelayToServer("showmoney", true);
|
AssignRelayToServer("showmoney", true);
|
||||||
AssignRelayToServer("setskill", true);
|
AssignRelayToServer("setskill", true);
|
||||||
AssignRelayToServer("readycheck", true);
|
AssignRelayToServer("readycheck", true);
|
||||||
|
commands.Add(new Command("debugjobassignment", "", (string[] args) => { }));
|
||||||
|
AssignRelayToServer("debugjobassignment", true);
|
||||||
|
|
||||||
AssignRelayToServer("givetalent", true);
|
AssignRelayToServer("givetalent", true);
|
||||||
AssignRelayToServer("unlocktalents", true);
|
AssignRelayToServer("unlocktalents", true);
|
||||||
@@ -2242,6 +2245,30 @@ namespace Barotrauma
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
commands.Add(new Command("listspamfilters", "Lists filters that are in the global spam filter.", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (!SpamServerFilters.GlobalSpamFilter.TryUnwrap(out var filter))
|
||||||
|
{
|
||||||
|
ThrowError("Global spam list is not initialized.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filter.Filters.Any())
|
||||||
|
{
|
||||||
|
NewMessage("Global spam list is empty.", GUIStyle.Green);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new();
|
||||||
|
|
||||||
|
foreach (var f in filter.Filters)
|
||||||
|
{
|
||||||
|
sb.AppendLine(f.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
NewMessage(sb.ToString(), GUIStyle.Green);
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("setplanthealth", "setplanthealth [value]: Sets the health of the selected plant in sub editor.", (string[] args) =>
|
commands.Add(new Command("setplanthealth", "setplanthealth [value]: Sets the health of the selected plant in sub editor.", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (1 > args.Length || Screen.Selected != GameMain.SubEditorScreen) { return; }
|
if (1 > args.Length || Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||||
@@ -3102,7 +3129,7 @@ namespace Barotrauma
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (LocationConnection connection in campaign.Map.CurrentLocation.Connections)
|
foreach (LocationConnection connection in campaign.Map.CurrentLocation.Connections)
|
||||||
{
|
{
|
||||||
NewMessage(" " + i + ". " + connection.OtherLocation(campaign.Map.CurrentLocation).Name, Color.White);
|
NewMessage(" " + i + ". " + connection.OtherLocation(campaign.Map.CurrentLocation).DisplayName, Color.White);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
ShowQuestionPrompt("Select a destination (0 - " + (campaign.Map.CurrentLocation.Connections.Count - 1) + "):", (string selectedDestination) =>
|
ShowQuestionPrompt("Select a destination (0 - " + (campaign.Map.CurrentLocation.Connections.Count - 1) + "):", (string selectedDestination) =>
|
||||||
|
|||||||
@@ -374,13 +374,12 @@ namespace Barotrauma
|
|||||||
btn.RectTransform.MinSize = new Point(0, (int)(btn.TextBlock.Rect.Height * 1.2f));
|
btn.RectTransform.MinSize = new Point(0, (int)(btn.TextBlock.Rect.Height * 1.2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height) + GUI.IntScale(16));
|
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height + textContent.AbsoluteSpacing) + GUI.IntScale(16));
|
||||||
content.RectTransform.MinSize = new Point(0, content.Children.Sum(c => c.Rect.Height));
|
content.RectTransform.MinSize = new Point(0, content.Children.Sum(c => c.Rect.Height));
|
||||||
|
|
||||||
// Recalculate the text size as it is scaled up and no longer matching the text height due to the textContent's minSize increasing
|
// Recalculate the text size as it is scaled up and no longer matching the text height due to the textContent's minSize increasing
|
||||||
textBlock.CalculateHeightFromText();
|
textBlock.CalculateHeightFromText();
|
||||||
textBlock.TextAlignment = Alignment.TopLeft;
|
textBlock.TextAlignment = Alignment.TopLeft;
|
||||||
//content.RectTransform.MinSize = new Point(0, textContent.Rect.Height);
|
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -16,6 +16,11 @@ partial class EventObjectiveAction : EventAction
|
|||||||
int width = 450,
|
int width = 450,
|
||||||
int height = 80)
|
int height = 80)
|
||||||
{
|
{
|
||||||
|
if (Type == SegmentActionType.AddIfNotFound)
|
||||||
|
{
|
||||||
|
if (ObjectiveManager.IsSegmentActive(Identifier)) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
ObjectiveManager.Segment? segment = null;
|
ObjectiveManager.Segment? segment = null;
|
||||||
// Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance)
|
// Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance)
|
||||||
if (Type == SegmentActionType.Trigger)
|
if (Type == SegmentActionType.Trigger)
|
||||||
@@ -24,7 +29,8 @@ partial class EventObjectiveAction : EventAction
|
|||||||
new ObjectiveManager.Segment.Text(TextTag, width, height, Anchor.Center),
|
new ObjectiveManager.Segment.Text(TextTag, width, height, Anchor.Center),
|
||||||
new ObjectiveManager.Segment.Video(videoFile, TextTag, width, height));
|
new ObjectiveManager.Segment.Video(videoFile, TextTag, width, height));
|
||||||
}
|
}
|
||||||
else if (Type == SegmentActionType.Add)
|
else if (Type == SegmentActionType.Add ||
|
||||||
|
Type == SegmentActionType.AddIfNotFound)
|
||||||
{
|
{
|
||||||
segment = ObjectiveManager.Segment.CreateObjectiveSegment(Identifier, !ObjectiveTag.IsEmpty ? ObjectiveTag : Identifier);
|
segment = ObjectiveManager.Segment.CreateObjectiveSegment(Identifier, !ObjectiveTag.IsEmpty ? ObjectiveTag : Identifier);
|
||||||
}
|
}
|
||||||
@@ -33,10 +39,12 @@ partial class EventObjectiveAction : EventAction
|
|||||||
segment.CanBeCompleted = CanBeCompleted;
|
segment.CanBeCompleted = CanBeCompleted;
|
||||||
segment.ParentId = ParentObjectiveId;
|
segment.ParentId = ParentObjectiveId;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case SegmentActionType.Trigger:
|
case SegmentActionType.Trigger:
|
||||||
case SegmentActionType.Add:
|
case SegmentActionType.Add:
|
||||||
|
case SegmentActionType.AddIfNotFound:
|
||||||
ObjectiveManager.TriggerSegment(segment);
|
ObjectiveManager.TriggerSegment(segment);
|
||||||
break;
|
break;
|
||||||
case SegmentActionType.Complete:
|
case SegmentActionType.Complete:
|
||||||
|
|||||||
+7
-10
@@ -1,22 +1,19 @@
|
|||||||
|
#nullable enable
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma;
|
namespace Barotrauma;
|
||||||
|
|
||||||
partial class TutorialHighlightAction : EventAction
|
partial class HighlightAction : EventAction
|
||||||
{
|
{
|
||||||
private static readonly Color highlightColor = Color.Orange;
|
partial void SetHighlightProjSpecific(Entity entity, IEnumerable<Character>? targetCharacters)
|
||||||
|
|
||||||
partial void UpdateProjSpecific()
|
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.GameMode is not TutorialMode) { return; }
|
if (targetCharacters != null && !targetCharacters.Contains(Character.Controlled))
|
||||||
foreach (var target in ParentEvent.GetTargets(TargetTag))
|
|
||||||
{
|
{
|
||||||
SetHighlight(target);
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void SetHighlight(Entity entity)
|
|
||||||
{
|
|
||||||
if (entity is Item i)
|
if (entity is Item i)
|
||||||
{
|
{
|
||||||
SetItemHighlight(i);
|
SetItemHighlight(i);
|
||||||
@@ -47,7 +47,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float theoreticalMaxMonsterStrength = 10000;
|
float theoreticalMaxMonsterStrength = 10000;
|
||||||
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * (GameMain.GameSession?.LevelData?.Difficulty ?? 0f) / 100;
|
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * (GameMain.GameSession?.Level?.Difficulty ?? 0f) / 100;
|
||||||
float absoluteMonsterStrength = monsterStrength / theoreticalMaxMonsterStrength;
|
float absoluteMonsterStrength = monsterStrength / theoreticalMaxMonsterStrength;
|
||||||
float relativeMonsterStrength = monsterStrength / relativeMaxMonsterStrength;
|
float relativeMonsterStrength = monsterStrength / relativeMaxMonsterStrength;
|
||||||
|
|
||||||
@@ -581,7 +581,14 @@ namespace Barotrauma
|
|||||||
StatusEffect effect = StatusEffect.Load(subElement, $"EventManager.ClientRead ({eventIdentifier})");
|
StatusEffect effect = StatusEffect.Load(subElement, $"EventManager.ClientRead ({eventIdentifier})");
|
||||||
foreach (Entity target in targets)
|
foreach (Entity target in targets)
|
||||||
{
|
{
|
||||||
effect.Apply(effect.type, 1.0f, target, target as ISerializableEntity);
|
if (target is Item item)
|
||||||
|
{
|
||||||
|
effect.Apply(effect.type, 1.0f, item, item.AllPropertyObjects);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effect.Apply(effect.type, 1.0f, target, target as ISerializableEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ namespace Barotrauma
|
|||||||
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
|
||||||
if (requiredDeliveryAmount > items.Count)
|
if (requiredDeliveryAmount > items.Count)
|
||||||
{
|
{
|
||||||
DebugConsole.AddWarning($"Error in mission \"{Prefab.Identifier}\". Required delivery amount is {requiredDeliveryAmount} but there's only {items.Count} items to deliver.");
|
DebugConsole.AddWarning($"Error in mission \"{Prefab.Identifier}\". Required delivery amount is {requiredDeliveryAmount} but there's only {items.Count} items to deliver.",
|
||||||
|
contentPackage: Prefab.ContentPackage);
|
||||||
requiredDeliveryAmount = items.Count;
|
requiredDeliveryAmount = items.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,13 @@ namespace Barotrauma
|
|||||||
void GiveMissionExperience(CharacterInfo info)
|
void GiveMissionExperience(CharacterInfo info)
|
||||||
{
|
{
|
||||||
if (info == null) { return; }
|
if (info == null) { return; }
|
||||||
var experienceGainMultiplierIndividual = new AbilityMissionExperienceGainMultiplier(this, 1f);
|
var experienceGainMultiplierIndividual = new AbilityMissionExperienceGainMultiplier(this, 1f, info.Character);
|
||||||
|
//check if anyone else in the crew has talents that could give a bonus to this one
|
||||||
|
foreach (var c in crew)
|
||||||
|
{
|
||||||
|
if (c == info.Character) { continue; }
|
||||||
|
c.CheckTalents(AbilityEffectType.OnAllyGainMissionExperience, experienceGainMultiplierIndividual);
|
||||||
|
}
|
||||||
info.Character?.CheckTalents(AbilityEffectType.OnGainMissionExperience, experienceGainMultiplierIndividual);
|
info.Character?.CheckTalents(AbilityEffectType.OnGainMissionExperience, experienceGainMultiplierIndividual);
|
||||||
info.GiveExperience((int)(experienceGain * experienceGainMultiplierIndividual.Value));
|
info.GiveExperience((int)(experienceGain * experienceGainMultiplierIndividual.Value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,30 +247,33 @@ namespace Barotrauma
|
|||||||
UpdateCrew();
|
UpdateCrew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateHireables()
|
||||||
|
{
|
||||||
|
UpdateHireables(campaign?.CurrentLocation);
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateHireables(Location location)
|
private void UpdateHireables(Location location)
|
||||||
{
|
{
|
||||||
if (hireableList != null)
|
if (hireableList == null) { return; }
|
||||||
|
hireableList.Content.Children.ToList().ForEach(c => hireableList.RemoveChild(c));
|
||||||
|
var hireableCharacters = location.GetHireableCharacters();
|
||||||
|
if (hireableCharacters.None())
|
||||||
{
|
{
|
||||||
hireableList.Content.Children.ToList().ForEach(c => hireableList.RemoveChild(c));
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), hireableList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
||||||
var hireableCharacters = location.GetHireableCharacters();
|
|
||||||
if (hireableCharacters.None())
|
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), hireableList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
CanBeFocused = false
|
||||||
{
|
};
|
||||||
CanBeFocused = false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (CharacterInfo c in hireableCharacters)
|
|
||||||
{
|
|
||||||
if (c == null) { continue; }
|
|
||||||
CreateCharacterFrame(c, hireableList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sortingDropDown.SelectItem(SortingMethod.JobAsc);
|
|
||||||
hireableList.UpdateScrollBarSize();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (CharacterInfo c in hireableCharacters)
|
||||||
|
{
|
||||||
|
if (c == null) { continue; }
|
||||||
|
CreateCharacterFrame(c, hireableList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortingDropDown.SelectItem(SortingMethod.JobAsc);
|
||||||
|
hireableList.UpdateScrollBarSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetHireables(Location location, List<CharacterInfo> availableHires)
|
public void SetHireables(Location location, List<CharacterInfo> availableHires)
|
||||||
@@ -434,7 +437,7 @@ namespace Barotrauma
|
|||||||
if (listBox != crewList)
|
if (listBox != crewList)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
|
||||||
TextManager.FormatCurrency(characterInfo.Salary),
|
TextManager.FormatCurrency(HireManager.GetSalaryFor(characterInfo)),
|
||||||
textAlignment: Alignment.Center)
|
textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
@@ -692,11 +695,8 @@ namespace Barotrauma
|
|||||||
private void SetTotalHireCost()
|
private void SetTotalHireCost()
|
||||||
{
|
{
|
||||||
if (pendingList == null || totalBlock == null || validateHiresButton == null) { return; }
|
if (pendingList == null || totalBlock == null || validateHiresButton == null) { return; }
|
||||||
int total = 0;
|
var infos = pendingList.Content.Children.Select(static c => ((InfoSkill)c.UserData).CharacterInfo).ToArray();
|
||||||
pendingList.Content.Children.ForEach(c =>
|
int total = HireManager.GetSalaryFor(infos);
|
||||||
{
|
|
||||||
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
|
||||||
});
|
|
||||||
totalBlock.Text = TextManager.FormatCurrency(total);
|
totalBlock.Text = TextManager.FormatCurrency(total);
|
||||||
bool enoughMoney = campaign == null || campaign.CanAfford(total);
|
bool enoughMoney = campaign == null || campaign.CanAfford(total);
|
||||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||||
@@ -718,14 +718,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (nonDuplicateHires.None()) { return false; }
|
if (nonDuplicateHires.None()) { return false; }
|
||||||
|
|
||||||
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
int total = HireManager.GetSalaryFor(nonDuplicateHires);
|
||||||
|
|
||||||
if (!campaign.CanAfford(total)) { return false; }
|
if (!campaign.CanAfford(total)) { return false; }
|
||||||
|
|
||||||
bool atLeastOneHired = false;
|
bool atLeastOneHired = false;
|
||||||
foreach (CharacterInfo ci in nonDuplicateHires)
|
foreach (CharacterInfo ci in nonDuplicateHires)
|
||||||
{
|
{
|
||||||
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci))
|
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci, Character.Controlled))
|
||||||
{
|
{
|
||||||
atLeastOneHired = true;
|
atLeastOneHired = true;
|
||||||
}
|
}
|
||||||
@@ -741,7 +741,7 @@ namespace Barotrauma
|
|||||||
SelectCharacter(null, null, null);
|
SelectCharacter(null, null, null);
|
||||||
var dialog = new GUIMessageBox(
|
var dialog = new GUIMessageBox(
|
||||||
TextManager.Get("newcrewmembers"),
|
TextManager.Get("newcrewmembers"),
|
||||||
TextManager.GetWithVariable("crewhiredmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
|
TextManager.GetWithVariable("crewhiredmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.DisplayName),
|
||||||
new LocalizedString[] { TextManager.Get("Ok") });
|
new LocalizedString[] { TextManager.Get("Ok") });
|
||||||
dialog.Buttons[0].OnClicked += dialog.Close;
|
dialog.Buttons[0].OnClicked += dialog.Close;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -512,10 +512,18 @@ namespace Barotrauma
|
|||||||
soundStr += " (stopped)";
|
soundStr += " (stopped)";
|
||||||
clr *= 0.5f;
|
clr *= 0.5f;
|
||||||
}
|
}
|
||||||
else if (playingSoundChannel.Muffled)
|
else
|
||||||
{
|
{
|
||||||
soundStr += " (muffled)";
|
if (playingSoundChannel.Muffled)
|
||||||
clr = Color.Lerp(clr, Color.LightGray, 0.5f);
|
{
|
||||||
|
soundStr += " (muffled)";
|
||||||
|
clr = Color.Lerp(clr, Color.LightGray, 0.5f);
|
||||||
|
}
|
||||||
|
if (playingSoundChannel.FadingOutAndDisposing)
|
||||||
|
{
|
||||||
|
soundStr += ". Fading out...";
|
||||||
|
clr = Color.Lerp(clr, Color.Black, 0.15f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2163,10 +2171,10 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GUIMessageBox AskForConfirmation(LocalizedString header, LocalizedString body, Action onConfirm, Action onDeny = null)
|
public static GUIMessageBox AskForConfirmation(LocalizedString header, LocalizedString body, Action onConfirm, Action onDeny = null, Vector2? relativeSize = null, Point? minSize = null)
|
||||||
{
|
{
|
||||||
LocalizedString[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
|
LocalizedString[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
|
||||||
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
|
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons, relativeSize: relativeSize ?? new Vector2(0.2f, 0.175f), minSize: minSize ?? new Point(300, 175));
|
||||||
|
|
||||||
// Cancel button
|
// Cancel button
|
||||||
msgBox.Buttons[1].OnClicked = delegate
|
msgBox.Buttons[1].OnClicked = delegate
|
||||||
|
|||||||
@@ -775,23 +775,30 @@ namespace Barotrauma
|
|||||||
toolTipBlock.UserData = toolTip;
|
toolTipBlock.UserData = toolTip;
|
||||||
}
|
}
|
||||||
|
|
||||||
toolTipBlock.RectTransform.AbsoluteOffset =
|
CalculateOffset();
|
||||||
RectTransform.CalculateAnchorPoint(anchor, targetElement) +
|
|
||||||
RectTransform.CalculatePivotOffset(pivot, toolTipBlock.RectTransform.NonScaledSize);
|
|
||||||
|
|
||||||
if (toolTipBlock.Rect.Right > GameMain.GraphicsWidth - 10)
|
if (toolTipBlock.Rect.Right > GameMain.GraphicsWidth - 10)
|
||||||
{
|
{
|
||||||
toolTipBlock.RectTransform.AbsoluteOffset -= new Point(toolTipBlock.Rect.Width + targetElement.Width, 0);
|
anchor = RectTransform.MoveAnchorLeft(anchor);
|
||||||
|
pivot = (Pivot)RectTransform.MoveAnchorRight((Anchor)pivot);
|
||||||
|
CalculateOffset();
|
||||||
}
|
}
|
||||||
if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10)
|
if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10)
|
||||||
{
|
{
|
||||||
toolTipBlock.RectTransform.AbsoluteOffset -= new Point(
|
anchor = RectTransform.MoveAnchorTop(anchor);
|
||||||
0,
|
pivot = (Pivot)RectTransform.MoveAnchorBottom((Anchor)pivot);
|
||||||
toolTipBlock.Rect.Bottom - (GameMain.GraphicsHeight - 10));
|
CalculateOffset();
|
||||||
}
|
}
|
||||||
toolTipBlock.SetTextPos();
|
toolTipBlock.SetTextPos();
|
||||||
|
|
||||||
toolTipBlock.DrawManually(spriteBatch);
|
toolTipBlock.DrawManually(spriteBatch);
|
||||||
|
|
||||||
|
void CalculateOffset()
|
||||||
|
{
|
||||||
|
toolTipBlock.RectTransform.AbsoluteOffset =
|
||||||
|
RectTransform.CalculateAnchorPoint(anchor, targetElement) +
|
||||||
|
RectTransform.CalculatePivotOffset(pivot, toolTipBlock.RectTransform.NonScaledSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -81,6 +82,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool FlashOnAutoCloseCondition { get; set; }
|
public bool FlashOnAutoCloseCondition { get; set; }
|
||||||
|
|
||||||
|
public Action OnEnterPressed { get; set; }
|
||||||
|
|
||||||
public Type MessageBoxType => type;
|
public Type MessageBoxType => type;
|
||||||
|
|
||||||
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
||||||
@@ -89,6 +92,10 @@ namespace Barotrauma
|
|||||||
: this(headerText, text, new LocalizedString[] { "OK" }, relativeSize, minSize, type: type)
|
: this(headerText, text, new LocalizedString[] { "OK" }, relativeSize, minSize, type: type)
|
||||||
{
|
{
|
||||||
this.Buttons[0].OnClicked = Close;
|
this.Buttons[0].OnClicked = Close;
|
||||||
|
OnEnterPressed = () =>
|
||||||
|
{
|
||||||
|
Buttons[0].OnClicked(Buttons[0], Buttons[0].UserData);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons,
|
public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons,
|
||||||
@@ -516,6 +523,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
if (PlayerInput.KeyHit(Keys.Enter))
|
||||||
|
{
|
||||||
|
OnEnterPressed?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
if (Draggable)
|
if (Draggable)
|
||||||
{
|
{
|
||||||
GUIComponent parent = GUI.MouseOn?.Parent?.Parent;
|
GUIComponent parent = GUI.MouseOn?.Parent?.Parent;
|
||||||
|
|||||||
@@ -18,6 +18,20 @@ namespace Barotrauma
|
|||||||
public GUIButton PlusButton { get; private set; }
|
public GUIButton PlusButton { get; private set; }
|
||||||
public GUIButton MinusButton { get; private set; }
|
public GUIButton MinusButton { get; private set; }
|
||||||
|
|
||||||
|
private void UpdatePlusMinusButtonVisibility()
|
||||||
|
{
|
||||||
|
if (ForceShowPlusMinusButtons
|
||||||
|
|| inputType == NumberType.Int
|
||||||
|
|| (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
|
||||||
|
{
|
||||||
|
ShowPlusMinusButtons();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HidePlusMinusButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private NumberType inputType;
|
private NumberType inputType;
|
||||||
public NumberType InputType
|
public NumberType InputType
|
||||||
{
|
{
|
||||||
@@ -26,15 +40,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (inputType == value) { return; }
|
if (inputType == value) { return; }
|
||||||
inputType = value;
|
inputType = value;
|
||||||
if (inputType == NumberType.Int ||
|
UpdatePlusMinusButtonVisibility();
|
||||||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
|
|
||||||
{
|
|
||||||
ShowPlusMinusButtons();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HidePlusMinusButtons();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,15 +52,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
minValueFloat = value;
|
minValueFloat = value;
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
if (inputType == NumberType.Int ||
|
UpdatePlusMinusButtonVisibility();
|
||||||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
|
|
||||||
{
|
|
||||||
ShowPlusMinusButtons();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HidePlusMinusButtons();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public float? MaxValueFloat
|
public float? MaxValueFloat
|
||||||
@@ -64,15 +62,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
maxValueFloat = value;
|
maxValueFloat = value;
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
if (inputType == NumberType.Int ||
|
UpdatePlusMinusButtonVisibility();
|
||||||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
|
|
||||||
{
|
|
||||||
ShowPlusMinusButtons();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HidePlusMinusButtons();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +86,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool forceShowPlusMinusButtons;
|
||||||
|
|
||||||
|
public bool ForceShowPlusMinusButtons
|
||||||
|
{
|
||||||
|
get { return forceShowPlusMinusButtons; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (forceShowPlusMinusButtons == value) { return; }
|
||||||
|
forceShowPlusMinusButtons = value;
|
||||||
|
UpdatePlusMinusButtonVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int decimalsToDisplay = 1;
|
private int decimalsToDisplay = 1;
|
||||||
public int DecimalsToDisplay
|
public int DecimalsToDisplay
|
||||||
{
|
{
|
||||||
@@ -184,7 +187,7 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool WrapAround;
|
public bool WrapAround;
|
||||||
|
|
||||||
public float valueStep;
|
public float ValueStep;
|
||||||
|
|
||||||
private float pressedTimer;
|
private float pressedTimer;
|
||||||
private readonly float pressedDelay = 0.5f;
|
private readonly float pressedDelay = 0.5f;
|
||||||
@@ -339,12 +342,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (inputType == NumberType.Int)
|
if (inputType == NumberType.Int)
|
||||||
{
|
{
|
||||||
IntValue -= valueStep > 0 ? (int)valueStep : 1;
|
IntValue -= ValueStep > 0 ? (int)ValueStep : 1;
|
||||||
ClampIntValue();
|
ClampIntValue();
|
||||||
}
|
}
|
||||||
else if (maxValueFloat.HasValue && minValueFloat.HasValue)
|
else if (maxValueFloat.HasValue && minValueFloat.HasValue)
|
||||||
{
|
{
|
||||||
FloatValue -= valueStep > 0 ? valueStep : Round();
|
FloatValue -= ValueStep > 0 ? ValueStep : Round();
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,12 +356,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (inputType == NumberType.Int)
|
if (inputType == NumberType.Int)
|
||||||
{
|
{
|
||||||
IntValue += valueStep > 0 ? (int)valueStep : 1;
|
IntValue += ValueStep > 0 ? (int)ValueStep : 1;
|
||||||
ClampIntValue();
|
ClampIntValue();
|
||||||
}
|
}
|
||||||
else if (inputType == NumberType.Float)
|
else if (inputType == NumberType.Float)
|
||||||
{
|
{
|
||||||
FloatValue += valueStep > 0 ? valueStep : Round();
|
FloatValue += ValueStep > 0 ? ValueStep : Round();
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,13 +313,18 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public class GUIColor : GUISelector<GUIColorPrefab>
|
public class GUIColor : GUISelector<GUIColorPrefab>
|
||||||
{
|
{
|
||||||
public GUIColor(string identifier) : base(identifier) { }
|
private readonly Color fallbackColor;
|
||||||
|
|
||||||
|
public GUIColor(string identifier, Color fallbackColor) : base(identifier)
|
||||||
|
{
|
||||||
|
this.fallbackColor = fallbackColor;
|
||||||
|
}
|
||||||
|
|
||||||
public Color Value
|
public Color Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Prefabs.ActivePrefab.Color;
|
return Prefabs?.ActivePrefab?.Color ?? fallbackColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,72 +75,72 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// General green color used for elements whose colors are set from code
|
/// General green color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor Green = new GUIColor("Green");
|
public readonly static GUIColor Green = new GUIColor("Green", new Color(154, 213, 163, 255));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General red color used for elements whose colors are set from code
|
/// General red color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor Orange = new GUIColor("Orange");
|
public readonly static GUIColor Orange = new GUIColor("Orange", new Color(243, 162, 50, 255));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General red color used for elements whose colors are set from code
|
/// General red color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor Red = new GUIColor("Red");
|
public readonly static GUIColor Red = new GUIColor("Red", new Color(245, 105, 105, 255));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General blue color used for elements whose colors are set from code
|
/// General blue color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor Blue = new GUIColor("Blue");
|
public readonly static GUIColor Blue = new GUIColor("Blue", new Color(126, 211, 224, 255));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General yellow color used for elements whose colors are set from code
|
/// General yellow color used for elements whose colors are set from code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor Yellow = new GUIColor("Yellow");
|
public readonly static GUIColor Yellow = new GUIColor("Yellow", new Color(255, 255, 0, 255));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Color to display the name of modded servers in the server list.
|
/// Color to display the name of modded servers in the server list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static GUIColor ModdedServerColor = new GUIColor("ModdedServerColor");
|
public readonly static GUIColor ModdedServerColor = new GUIColor("ModdedServerColor", new Color(154, 185, 160, 255));
|
||||||
|
|
||||||
public readonly static GUIColor ColorInventoryEmpty = new GUIColor("ColorInventoryEmpty");
|
public readonly static GUIColor ColorInventoryEmpty = new GUIColor("ColorInventoryEmpty", new Color(245, 105, 105, 255));
|
||||||
public readonly static GUIColor ColorInventoryHalf = new GUIColor("ColorInventoryHalf");
|
public readonly static GUIColor ColorInventoryHalf = new GUIColor("ColorInventoryHalf", new Color(243, 162, 50, 255));
|
||||||
public readonly static GUIColor ColorInventoryFull = new GUIColor("ColorInventoryFull");
|
public readonly static GUIColor ColorInventoryFull = new GUIColor("ColorInventoryFull", new Color(96, 222, 146, 255));
|
||||||
public readonly static GUIColor ColorInventoryBackground = new GUIColor("ColorInventoryBackground");
|
public readonly static GUIColor ColorInventoryBackground = new GUIColor("ColorInventoryBackground", new Color(56, 56, 56, 255));
|
||||||
public readonly static GUIColor ColorInventoryEmptyOverlay = new GUIColor("ColorInventoryEmptyOverlay");
|
public readonly static GUIColor ColorInventoryEmptyOverlay = new GUIColor("ColorInventoryEmptyOverlay", new Color(125, 125, 125, 255));
|
||||||
|
|
||||||
public readonly static GUIColor TextColorNormal = new GUIColor("TextColorNormal");
|
public readonly static GUIColor TextColorNormal = new GUIColor("TextColorNormal", new Color(228, 217, 167, 255));
|
||||||
public readonly static GUIColor TextColorBright = new GUIColor("TextColorBright");
|
public readonly static GUIColor TextColorBright = new GUIColor("TextColorBright", new Color(255, 255, 255, 255));
|
||||||
public readonly static GUIColor TextColorDark = new GUIColor("TextColorDark");
|
public readonly static GUIColor TextColorDark = new GUIColor("TextColorDark", new Color(0, 0, 0, 230));
|
||||||
public readonly static GUIColor TextColorDim = new GUIColor("TextColorDim");
|
public readonly static GUIColor TextColorDim = new GUIColor("TextColorDim", new Color(153, 153, 153, 153));
|
||||||
|
|
||||||
public readonly static GUIColor ItemQualityColorPoor = new GUIColor("ItemQualityColorPoor");
|
public readonly static GUIColor ItemQualityColorPoor = new GUIColor("ItemQualityColorPoor", new Color(128, 128, 128, 255));
|
||||||
public readonly static GUIColor ItemQualityColorNormal = new GUIColor("ItemQualityColorNormal");
|
public readonly static GUIColor ItemQualityColorNormal = new GUIColor("ItemQualityColorNormal", new Color(255, 255, 255, 255));
|
||||||
public readonly static GUIColor ItemQualityColorGood = new GUIColor("ItemQualityColorGood");
|
public readonly static GUIColor ItemQualityColorGood = new GUIColor("ItemQualityColorGood", new Color(144, 238, 144, 255));
|
||||||
public readonly static GUIColor ItemQualityColorExcellent = new GUIColor("ItemQualityColorExcellent");
|
public readonly static GUIColor ItemQualityColorExcellent = new GUIColor("ItemQualityColorExcellent", new Color(173, 216, 230, 255));
|
||||||
public readonly static GUIColor ItemQualityColorMasterwork = new GUIColor("ItemQualityColorMasterwork");
|
public readonly static GUIColor ItemQualityColorMasterwork = new GUIColor("ItemQualityColorMasterwork", new Color(147, 112, 219, 255));
|
||||||
|
|
||||||
public readonly static GUIColor ColorReputationVeryLow = new GUIColor("ColorReputationVeryLow");
|
public readonly static GUIColor ColorReputationVeryLow = new GUIColor("ColorReputationVeryLow", new Color(192, 60, 60, 255));
|
||||||
public readonly static GUIColor ColorReputationLow = new GUIColor("ColorReputationLow");
|
public readonly static GUIColor ColorReputationLow = new GUIColor("ColorReputationLow", new Color(203, 145, 23, 255));
|
||||||
public readonly static GUIColor ColorReputationNeutral = new GUIColor("ColorReputationNeutral");
|
public readonly static GUIColor ColorReputationNeutral = new GUIColor("ColorReputationNeutral", new Color(228, 217, 167, 255));
|
||||||
public readonly static GUIColor ColorReputationHigh = new GUIColor("ColorReputationHigh");
|
public readonly static GUIColor ColorReputationHigh = new GUIColor("ColorReputationHigh", new Color(51, 152, 64, 255));
|
||||||
public readonly static GUIColor ColorReputationVeryHigh = new GUIColor("ColorReputationVeryHigh");
|
public readonly static GUIColor ColorReputationVeryHigh = new GUIColor("ColorReputationVeryHigh", new Color(71, 160, 164, 255));
|
||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
public readonly static GUIColor EquipmentSlotIconColor = new GUIColor("EquipmentSlotIconColor");
|
public readonly static GUIColor EquipmentSlotIconColor = new GUIColor("EquipmentSlotIconColor", new Color(99, 70, 64, 255));
|
||||||
|
|
||||||
// Health HUD
|
// Health HUD
|
||||||
public readonly static GUIColor BuffColorLow = new GUIColor("BuffColorLow");
|
public readonly static GUIColor BuffColorLow = new GUIColor("BuffColorLow", new Color(66, 170, 73, 255));
|
||||||
public readonly static GUIColor BuffColorMedium = new GUIColor("BuffColorMedium");
|
public readonly static GUIColor BuffColorMedium = new GUIColor("BuffColorMedium", new Color(110, 168, 118, 255));
|
||||||
public readonly static GUIColor BuffColorHigh = new GUIColor("BuffColorHigh");
|
public readonly static GUIColor BuffColorHigh = new GUIColor("BuffColorHigh", new Color(154, 213, 163, 255));
|
||||||
|
|
||||||
public readonly static GUIColor DebuffColorLow = new GUIColor("DebuffColorLow");
|
public readonly static GUIColor DebuffColorLow = new GUIColor("DebuffColorLow", new Color(243, 162, 50, 255));
|
||||||
public readonly static GUIColor DebuffColorMedium = new GUIColor("DebuffColorMedium");
|
public readonly static GUIColor DebuffColorMedium = new GUIColor("DebuffColorMedium", new Color(155, 55, 55, 255));
|
||||||
public readonly static GUIColor DebuffColorHigh = new GUIColor("DebuffColorHigh");
|
public readonly static GUIColor DebuffColorHigh = new GUIColor("DebuffColorHigh", new Color(228, 27, 27, 255));
|
||||||
|
|
||||||
public readonly static GUIColor HealthBarColorLow = new GUIColor("HealthBarColorLow");
|
public readonly static GUIColor HealthBarColorLow = new GUIColor("HealthBarColorLow", new Color(255, 0, 0, 255));
|
||||||
public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium");
|
public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium", new Color(255, 165, 0, 255));
|
||||||
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh");
|
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh", new Color(78, 114, 88));
|
||||||
public readonly static GUIColor HealthBarColorPoisoned = new GUIColor("HealthBarColorPoisoned");
|
public readonly static GUIColor HealthBarColorPoisoned = new GUIColor("HealthBarColorPoisoned", new Color(100, 150, 0, 255));
|
||||||
|
|
||||||
private readonly static Point defaultItemFrameMargin = new Point(50, 56);
|
private readonly static Point defaultItemFrameMargin = new Point(50, 56);
|
||||||
|
|
||||||
|
|||||||
@@ -461,14 +461,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableArray<Vector2> cachedCaretPositions = ImmutableArray<Vector2>.Empty;
|
private ImmutableArray<Vector2> cachedCaretPositions = ImmutableArray<Vector2>.Empty;
|
||||||
|
//which text were the cached caret positions calculated for?
|
||||||
|
private string cachedCaretPositionsText;
|
||||||
public ImmutableArray<Vector2> GetAllCaretPositions()
|
public ImmutableArray<Vector2> GetAllCaretPositions()
|
||||||
{
|
{
|
||||||
if (cachedCaretPositions.Any())
|
string textDrawn = Censor ? CensoredText : Text.SanitizedValue;
|
||||||
|
if (cachedCaretPositions.Any() &&
|
||||||
|
textDrawn == cachedCaretPositionsText)
|
||||||
{
|
{
|
||||||
return cachedCaretPositions;
|
return cachedCaretPositions;
|
||||||
}
|
}
|
||||||
string textDrawn = Censor ? CensoredText : Text.SanitizedValue;
|
|
||||||
float w = Wrap
|
float w = Wrap
|
||||||
? (Rect.Width - Padding.X - Padding.Z) / TextScale
|
? (Rect.Width - Padding.X - Padding.Z) / TextScale
|
||||||
: float.PositiveInfinity;
|
: float.PositiveInfinity;
|
||||||
@@ -482,6 +484,7 @@ namespace Barotrauma
|
|||||||
.Select(p => p - new Vector2(alignmentXDiff, 0))
|
.Select(p => p - new Vector2(alignmentXDiff, 0))
|
||||||
.Select(p => p * TextScale + TextPos - Origin * TextScale)
|
.Select(p => p * TextScale + TextPos - Origin * TextScale)
|
||||||
.ToImmutableArray();
|
.ToImmutableArray();
|
||||||
|
cachedCaretPositionsText = textDrawn;
|
||||||
return cachedCaretPositions;
|
return cachedCaretPositions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -363,6 +363,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
CaretIndex = Math.Clamp(CaretIndex, 0, textBlock.Text.Length);
|
CaretIndex = Math.Clamp(CaretIndex, 0, textBlock.Text.Length);
|
||||||
var caretPositions = textBlock.GetAllCaretPositions();
|
var caretPositions = textBlock.GetAllCaretPositions();
|
||||||
|
if (CaretIndex >= caretPositions.Length)
|
||||||
|
{
|
||||||
|
throw new Exception($"Caret index was outside the bounds of the calculated caret positions. Index: {CaretIndex}, caret positions: {caretPositions.Length}, text: {textBlock.Text}");
|
||||||
|
}
|
||||||
caretPos = caretPositions[CaretIndex];
|
caretPos = caretPositions[CaretIndex];
|
||||||
caretPosDirty = false;
|
caretPosDirty = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -784,11 +784,95 @@ namespace Barotrauma
|
|||||||
#region Static methods
|
#region Static methods
|
||||||
public static Pivot MatchPivotToAnchor(Anchor anchor)
|
public static Pivot MatchPivotToAnchor(Anchor anchor)
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse(anchor.ToString(), out Pivot pivot))
|
return (Pivot)anchor;
|
||||||
|
}
|
||||||
|
public static Anchor MatchAnchorToPivot(Pivot pivot)
|
||||||
|
{
|
||||||
|
return (Anchor)pivot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the anchor to the left, keeping the vertical position unchanged (e.g. CenterRight -> CenterLeft)
|
||||||
|
/// </summary>
|
||||||
|
public static Anchor MoveAnchorLeft(Anchor anchor)
|
||||||
|
{
|
||||||
|
switch (anchor)
|
||||||
{
|
{
|
||||||
throw new Exception($"[RectTransform] Cannot match pivot to anchor {anchor}");
|
case Anchor.TopCenter:
|
||||||
|
case Anchor.TopRight:
|
||||||
|
return Anchor.TopLeft;
|
||||||
|
case Anchor.Center:
|
||||||
|
case Anchor.CenterRight:
|
||||||
|
return Anchor.CenterLeft;
|
||||||
|
case Anchor.BottomCenter:
|
||||||
|
case Anchor.BottomRight:
|
||||||
|
return Anchor.BottomLeft;
|
||||||
|
default:
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the anchor to the right, keeping the vertical position unchanged (e.g. CenterLeft -> CenterRight)
|
||||||
|
/// </summary>
|
||||||
|
public static Anchor MoveAnchorRight(Anchor anchor)
|
||||||
|
{
|
||||||
|
switch (anchor)
|
||||||
|
{
|
||||||
|
case Anchor.TopCenter:
|
||||||
|
case Anchor.TopLeft:
|
||||||
|
return Anchor.TopRight;
|
||||||
|
case Anchor.Center:
|
||||||
|
case Anchor.CenterLeft:
|
||||||
|
return Anchor.CenterRight;
|
||||||
|
case Anchor.BottomCenter:
|
||||||
|
case Anchor.BottomLeft:
|
||||||
|
return Anchor.BottomRight;
|
||||||
|
default:
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the anchor to the top, keeping the horizontal position unchanged (e.g. BottomCenter -> TopCenter)
|
||||||
|
/// </summary>
|
||||||
|
public static Anchor MoveAnchorTop(Anchor anchor)
|
||||||
|
{
|
||||||
|
switch (anchor)
|
||||||
|
{
|
||||||
|
case Anchor.CenterLeft:
|
||||||
|
case Anchor.BottomLeft:
|
||||||
|
return Anchor.TopLeft;
|
||||||
|
case Anchor.Center:
|
||||||
|
case Anchor.BottomCenter:
|
||||||
|
return Anchor.TopCenter;
|
||||||
|
case Anchor.CenterRight:
|
||||||
|
case Anchor.BottomRight:
|
||||||
|
return Anchor.TopRight;
|
||||||
|
default:
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves the anchor to the bottom, keeping the horizontal position unchanged (e.g. TopCenter -> BottomCenter)
|
||||||
|
/// </summary>
|
||||||
|
public static Anchor MoveAnchorBottom(Anchor anchor)
|
||||||
|
{
|
||||||
|
switch (anchor)
|
||||||
|
{
|
||||||
|
case Anchor.CenterLeft:
|
||||||
|
case Anchor.TopLeft:
|
||||||
|
return Anchor.BottomLeft;
|
||||||
|
case Anchor.Center:
|
||||||
|
case Anchor.TopCenter:
|
||||||
|
return Anchor.BottomCenter;
|
||||||
|
case Anchor.CenterRight:
|
||||||
|
case Anchor.TopRight:
|
||||||
|
return Anchor.BottomRight;
|
||||||
|
default:
|
||||||
|
return anchor;
|
||||||
}
|
}
|
||||||
return pivot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -811,11 +895,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Point CalculatePivotOffset(Pivot pivot, Point size)
|
public static Point CalculatePivotOffset(Pivot anchor, Point size)
|
||||||
{
|
{
|
||||||
int width = size.X;
|
int width = size.X;
|
||||||
int height = size.Y;
|
int height = size.Y;
|
||||||
switch (pivot)
|
switch (anchor)
|
||||||
{
|
{
|
||||||
case Pivot.TopLeft:
|
case Pivot.TopLeft:
|
||||||
return Point.Zero;
|
return Point.Zero;
|
||||||
@@ -836,7 +920,7 @@ namespace Barotrauma
|
|||||||
case Pivot.BottomRight:
|
case Pivot.BottomRight:
|
||||||
return new Point(-width, -height);
|
return new Point(-width, -height);
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(pivot.ToString());
|
throw new NotImplementedException(anchor.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace Barotrauma
|
|||||||
private readonly List<PurchasedItem> itemsToSell = new List<PurchasedItem>();
|
private readonly List<PurchasedItem> itemsToSell = new List<PurchasedItem>();
|
||||||
private readonly List<PurchasedItem> itemsToSellFromSub = new List<PurchasedItem>();
|
private readonly List<PurchasedItem> itemsToSellFromSub = new List<PurchasedItem>();
|
||||||
|
|
||||||
|
private GUIMessageBox deliveryPrompt;
|
||||||
|
|
||||||
private StoreTab activeTab = StoreTab.Buy;
|
private StoreTab activeTab = StoreTab.Buy;
|
||||||
private MapEntityCategory? selectedItemCategory;
|
private MapEntityCategory? selectedItemCategory;
|
||||||
private bool suppressBuySell;
|
private bool suppressBuySell;
|
||||||
@@ -341,9 +343,9 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
var panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
|
var panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
|
||||||
var storeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform)
|
var storeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, Anchor.BottomLeft)
|
||||||
{
|
{
|
||||||
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height)
|
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height - HUDLayoutSettings.ButtonAreaTop.Bottom)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -583,9 +585,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
// Shopping Crate ------------------------------------------------------------------------------------------------------------------------------------------
|
// Shopping Crate ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
var shoppingCrateContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, anchor: Anchor.TopRight)
|
var shoppingCrateContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, anchor: Anchor.BottomRight)
|
||||||
{
|
{
|
||||||
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height)
|
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height - HUDLayoutSettings.ButtonAreaTop.Bottom)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Stretch = true,
|
Stretch = true,
|
||||||
@@ -922,15 +924,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (itemPrefab.CanBeBoughtFrom(ActiveStore, out PriceInfo priceInfo) && itemPrefab.CanCharacterBuy())
|
if (itemPrefab.CanBeBoughtFrom(ActiveStore, out PriceInfo priceInfo) && itemPrefab.CanCharacterBuy())
|
||||||
{
|
{
|
||||||
|
|
||||||
bool isDailySpecial = ActiveStore.DailySpecials.Contains(itemPrefab);
|
bool isDailySpecial = ActiveStore.DailySpecials.Contains(itemPrefab);
|
||||||
var itemFrame = isDailySpecial ?
|
var itemFrame = isDailySpecial ?
|
||||||
storeDailySpecialsGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
storeDailySpecialsGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
||||||
storeBuyList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
storeBuyList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
||||||
if (CargoManager.GetPurchasedItem(ActiveStore, itemPrefab) is { } purchasedItem)
|
|
||||||
{
|
quantity = Math.Max(quantity - CargoManager.GetPurchasedItemCount(ActiveStore, itemPrefab), 0);
|
||||||
quantity = Math.Max(quantity - purchasedItem.Quantity, 0);
|
|
||||||
}
|
|
||||||
if (CargoManager.GetBuyCrateItem(ActiveStore, itemPrefab) is { } buyCrateItem)
|
if (CargoManager.GetBuyCrateItem(ActiveStore, itemPrefab) is { } buyCrateItem)
|
||||||
{
|
{
|
||||||
quantity = Math.Max(quantity - buyCrateItem.Quantity, 0);
|
quantity = Math.Max(quantity - buyCrateItem.Quantity, 0);
|
||||||
@@ -1245,9 +1244,9 @@ namespace Barotrauma
|
|||||||
int totalPrice = 0;
|
int totalPrice = 0;
|
||||||
if (ActiveStore != null)
|
if (ActiveStore != null)
|
||||||
{
|
{
|
||||||
foreach (PurchasedItem item in items)
|
foreach (PurchasedItem item in items.ToList())
|
||||||
{
|
{
|
||||||
if (!(item.ItemPrefab.GetPriceInfo(ActiveStore) is { } priceInfo)) { continue; }
|
if (item.ItemPrefab.GetPriceInfo(ActiveStore) is not { } priceInfo) { continue; }
|
||||||
GUINumberInput numInput = null;
|
GUINumberInput numInput = null;
|
||||||
if (!(listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier) is { } itemFrame))
|
if (!(listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier) is { } itemFrame))
|
||||||
{
|
{
|
||||||
@@ -1749,7 +1748,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add items already purchased
|
// Add items already purchased
|
||||||
CargoManager?.GetPurchasedItems(ActiveStore).ForEach(pi => AddNonEmptyOwnedItems(pi));
|
CargoManager?.GetPurchasedItems(ActiveStore).Where(pi => !pi.DeliverImmediately).ForEach(pi => AddNonEmptyOwnedItems(pi));
|
||||||
|
|
||||||
ownedItemsUpdateTimer = 0.0f;
|
ownedItemsUpdateTimer = 0.0f;
|
||||||
|
|
||||||
@@ -1959,14 +1958,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (NotImplementedException e)
|
catch (NotImplementedException e)
|
||||||
{
|
{
|
||||||
DebugConsole.LogError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
DebugConsole.LogError($"Error getting item availability: Unknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||||
}
|
}
|
||||||
if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
||||||
{
|
{
|
||||||
if (mode == StoreTab.Buy)
|
if (mode == StoreTab.Buy)
|
||||||
{
|
{
|
||||||
var purchasedItem = CargoManager.GetPurchasedItem(ActiveStore, item.ItemPrefab);
|
return Math.Max(item.Quantity - CargoManager.GetPurchasedItemCount(ActiveStore, item.ItemPrefab), 0);
|
||||||
if (purchasedItem != null) { return Math.Max(item.Quantity - purchasedItem.Quantity, 0); }
|
|
||||||
}
|
}
|
||||||
return item.Quantity;
|
return item.Quantity;
|
||||||
}
|
}
|
||||||
@@ -2093,16 +2091,57 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
||||||
if (itemsToPurchase.None() || Balance < totalPrice) { return false; }
|
if (itemsToPurchase.None() || Balance < totalPrice) { return false; }
|
||||||
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, true);
|
|
||||||
GameMain.Client?.SendCampaignState();
|
if (CampaignMode.AllowImmediateItemDelivery())
|
||||||
var dialog = new GUIMessageBox(
|
{
|
||||||
TextManager.Get("newsupplies"),
|
deliveryPrompt = new GUIMessageBox(
|
||||||
TextManager.GetWithVariable("suppliespurchasedmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
|
TextManager.Get("newsupplies"),
|
||||||
new LocalizedString[] { TextManager.Get("Ok") });
|
TextManager.Get("suppliespurchased.deliverymethod"),
|
||||||
dialog.Buttons[0].OnClicked += dialog.Close;
|
new LocalizedString[]
|
||||||
|
{
|
||||||
|
TextManager.Get("suppliespurchased.deliverymethod.deliverimmediately"),
|
||||||
|
TextManager.Get("suppliespurchased.deliverymethod.delivertosub")
|
||||||
|
});
|
||||||
|
deliveryPrompt.Buttons[0].OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
ConfirmPurchase(deliverImmediately: true);
|
||||||
|
deliveryPrompt.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
deliveryPrompt.Buttons[1].OnClicked = (btn, userdata) =>
|
||||||
|
{
|
||||||
|
ConfirmPurchase(deliverImmediately: false);
|
||||||
|
deliveryPrompt.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConfirmPurchase(deliverImmediately: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfirmPurchase(bool deliverImmediately)
|
||||||
|
{
|
||||||
|
itemsToPurchase.ForEach(it => it.DeliverImmediately = deliverImmediately);
|
||||||
|
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, removeFromCrate: true);
|
||||||
|
GameMain.Client?.SendCampaignState();
|
||||||
|
if (!deliverImmediately)
|
||||||
|
{
|
||||||
|
var dialog = new GUIMessageBox(
|
||||||
|
TextManager.Get("newsupplies"),
|
||||||
|
TextManager.GetWithVariable("suppliespurchasedmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.DisplayName));
|
||||||
|
dialog.Buttons[0].OnClicked += dialog.Close;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnDeselected()
|
||||||
|
{
|
||||||
|
deliveryPrompt?.Close();
|
||||||
|
deliveryPrompt = null;
|
||||||
|
}
|
||||||
|
|
||||||
private bool SellItems()
|
private bool SellItems()
|
||||||
{
|
{
|
||||||
if (!HasActiveTabPermissions()) { return false; }
|
if (!HasActiveTabPermissions()) { return false; }
|
||||||
@@ -2118,7 +2157,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (NotImplementedException e)
|
catch (NotImplementedException e)
|
||||||
{
|
{
|
||||||
DebugConsole.LogError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
DebugConsole.LogError($"Error confirming the store transaction: Unknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var itemsToRemove = new List<PurchasedItem>();
|
var itemsToRemove = new List<PurchasedItem>();
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
|
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
|
||||||
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUIStyle.LargeFont);
|
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.DisplayName), font: GUIStyle.LargeFont);
|
||||||
header.CalculateHeightFromText(0, true);
|
header.CalculateHeightFromText(0, true);
|
||||||
playerBalanceElement = CampaignUI.AddBalanceElement(header, new Vector2(1.0f, 1.5f));
|
playerBalanceElement = CampaignUI.AddBalanceElement(header, new Vector2(1.0f, 1.5f));
|
||||||
|
|
||||||
|
|||||||
@@ -165,6 +165,11 @@ namespace Barotrauma
|
|||||||
public TabMenu()
|
public TabMenu()
|
||||||
{
|
{
|
||||||
if (!initialized) { Initialize(); }
|
if (!initialized) { Initialize(); }
|
||||||
|
if (Level.Loaded == null)
|
||||||
|
{
|
||||||
|
//make sure we're not trying to view e.g. mission or reputation info if the tab menu is opened in the test mode
|
||||||
|
SelectedTab = InfoFrameTab.Crew;
|
||||||
|
}
|
||||||
CreateInfoFrame(SelectedTab);
|
CreateInfoFrame(SelectedTab);
|
||||||
SelectInfoFrameTab(SelectedTab);
|
SelectInfoFrameTab(SelectedTab);
|
||||||
}
|
}
|
||||||
@@ -303,7 +308,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var missionBtn = createTabButton(InfoFrameTab.Mission, "mission");
|
var missionBtn = createTabButton(InfoFrameTab.Mission, "mission");
|
||||||
eventLogNotification = GameSession.CreateNotificationIcon(missionBtn);
|
eventLogNotification = GameSession.CreateNotificationIcon(missionBtn);
|
||||||
eventLogNotification.Visible = GameMain.GameSession.EventManager?.EventLog?.UnreadEntries ?? false;
|
eventLogNotification.Visible = GameMain.GameSession?.EventManager?.EventLog?.UnreadEntries ?? false;
|
||||||
if (eventLogNotification.Visible)
|
if (eventLogNotification.Visible)
|
||||||
{
|
{
|
||||||
eventLogNotification.Pulsate(Vector2.One, Vector2.One * 2, 1.0f);
|
eventLogNotification.Pulsate(Vector2.One, Vector2.One * 2, 1.0f);
|
||||||
@@ -1508,7 +1513,7 @@ namespace Barotrauma
|
|||||||
portraitImage.RectTransform.NonScaledSize = new Point(Math.Min((int)(portraitImage.Rect.Size.Y * portraitAspectRatio), portraitImage.Rect.Width), portraitImage.Rect.Size.Y);
|
portraitImage.RectTransform.NonScaledSize = new Point(Math.Min((int)(portraitImage.Rect.Size.Y * portraitAspectRatio), portraitImage.Rect.Width), portraitImage.Rect.Size.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Name, font: GUIStyle.LargeFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.DisplayName, font: GUIStyle.LargeFont);
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont);
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont);
|
||||||
|
|
||||||
if (location.Faction?.Prefab != null)
|
if (location.Faction?.Prefab != null)
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace Barotrauma
|
|||||||
else if (Tile)
|
else if (Tile)
|
||||||
{
|
{
|
||||||
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
||||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color, startOffset: uvOffset);
|
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color: color, startOffset: uvOffset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1110,7 +1110,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static UpgradeFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
public static UpgradeFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
||||||
{
|
{
|
||||||
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
|
int price = prefab.Price.GetBuyPrice(prefab, campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
|
||||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1267,7 +1267,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
||||||
("[upgradename]", prefab.Name),
|
("[upgradename]", prefab.Name),
|
||||||
("[amount]", prefab.Price.GetBuyPrice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation, characterList).ToString()));
|
("[amount]", prefab.Price.GetBuyPrice(prefab, Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation, characterList).ToString()));
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||||
{
|
{
|
||||||
if (GameMain.NetworkMember != null)
|
if (GameMain.NetworkMember != null)
|
||||||
@@ -1682,7 +1682,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUITextBlock priceLabel = (GUITextBlock)buttonParent.FindChild(UpgradeStoreUserData.PriceLabel, recursive: true);
|
GUITextBlock priceLabel = (GUITextBlock)buttonParent.FindChild(UpgradeStoreUserData.PriceLabel, recursive: true);
|
||||||
priceLabel.Visible = true;
|
priceLabel.Visible = true;
|
||||||
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
|
int price = prefab.Price.GetBuyPrice(prefab, campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
|
||||||
|
|
||||||
if (!WaitForServerUpdate)
|
if (!WaitForServerUpdate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,6 +124,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private Viewport defaultViewport;
|
private Viewport defaultViewport;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NOTE: Use very carefully. You need to ensure that you ALWAYS unsubscribe from this when you no longer need the subscriber!
|
||||||
|
/// If you're subscribing to this from something else than a singleton or something that there's only ever one instance of, you're probably in dangerous territory.
|
||||||
|
/// </summary>
|
||||||
public event Action ResolutionChanged;
|
public event Action ResolutionChanged;
|
||||||
|
|
||||||
private bool exiting;
|
private bool exiting;
|
||||||
@@ -407,7 +411,7 @@ namespace Barotrauma
|
|||||||
//do this here because we need it for the loading screen
|
//do this here because we need it for the loading screen
|
||||||
WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice);
|
WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice);
|
||||||
|
|
||||||
Quad.Init(GraphicsDevice);
|
GraphicsQuad.Init(GraphicsDevice);
|
||||||
|
|
||||||
loadingScreenOpen = true;
|
loadingScreenOpen = true;
|
||||||
TitleScreen = new LoadingScreen(GraphicsDevice)
|
TitleScreen = new LoadingScreen(GraphicsDevice)
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
catch (NotImplementedException e)
|
catch (NotImplementedException e)
|
||||||
{
|
{
|
||||||
DebugConsole.LogError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
DebugConsole.LogError($"Error selling items: unknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ namespace Barotrauma
|
|||||||
case InteractionType.MedicalClinic:
|
case InteractionType.MedicalClinic:
|
||||||
CampaignUI.MedicalClinic?.OnDeselected();
|
CampaignUI.MedicalClinic?.OnDeselected();
|
||||||
break;
|
break;
|
||||||
|
case InteractionType.Store:
|
||||||
|
CampaignUI.Store?.OnDeselected();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +124,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return AllowedToManageCampaign(ClientPermissions.ManageMoney);
|
return AllowedToManageCampaign(ClientPermissions.ManageMoney);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool AllowImmediateItemDelivery()
|
||||||
|
{
|
||||||
|
if (GameMain.Client == null) { return true; }
|
||||||
|
return
|
||||||
|
GameMain.Client.ServerSettings.AllowImmediateItemDelivery ||
|
||||||
|
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||||
|
GameMain.Client.IsServerOwner;
|
||||||
|
}
|
||||||
|
|
||||||
protected GUIButton CreateEndRoundButton()
|
protected GUIButton CreateEndRoundButton()
|
||||||
{
|
{
|
||||||
int buttonWidth = (int)(450 * GUI.xScale * (GUI.IsUltrawide ? 3.0f : 1.0f));
|
int buttonWidth = (int)(450 * GUI.xScale * (GUI.IsUltrawide ? 3.0f : 1.0f));
|
||||||
@@ -182,12 +195,12 @@ namespace Barotrauma
|
|||||||
if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub))
|
if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub))
|
||||||
{
|
{
|
||||||
string textTag = availableTransition == TransitionType.ProgressToNextLocation ? "EnterLocation" : "EnterEmptyLocation";
|
string textTag = availableTransition == TransitionType.ProgressToNextLocation ? "EnterLocation" : "EnterEmptyLocation";
|
||||||
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]");
|
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.EndLocation?.DisplayName ?? "[ERROR]");
|
||||||
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TransitionType.LeaveLocation:
|
case TransitionType.LeaveLocation:
|
||||||
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.DisplayName ?? "[ERROR]");
|
||||||
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
||||||
break;
|
break;
|
||||||
case TransitionType.ReturnToPreviousLocation:
|
case TransitionType.ReturnToPreviousLocation:
|
||||||
@@ -195,7 +208,7 @@ namespace Barotrauma
|
|||||||
if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub))
|
if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub))
|
||||||
{
|
{
|
||||||
string textTag = availableTransition == TransitionType.ReturnToPreviousLocation ? "EnterLocation" : "EnterEmptyLocation";
|
string textTag = availableTransition == TransitionType.ReturnToPreviousLocation ? "EnterLocation" : "EnterEmptyLocation";
|
||||||
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.StartLocation?.DisplayName ?? "[ERROR]");
|
||||||
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -211,7 +224,7 @@ namespace Barotrauma
|
|||||||
endRoundButton.Color = GUIStyle.Red * 0.7f;
|
endRoundButton.Color = GUIStyle.Red * 0.7f;
|
||||||
endRoundButton.HoverColor = GUIStyle.Red;
|
endRoundButton.HoverColor = GUIStyle.Red;
|
||||||
}
|
}
|
||||||
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]");
|
buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.DisplayName ?? "[ERROR]");
|
||||||
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
allowEndingRound = !ForceMapUI && !ShowCampaignUI;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+14
-5
@@ -535,7 +535,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool refreshCampaignUI = false;
|
bool refreshCampaignUI = false;
|
||||||
|
|
||||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
|
if (GameMain.GameSession?.GameMode is not MultiPlayerCampaign campaign || campaignID != campaign.CampaignID)
|
||||||
{
|
{
|
||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
||||||
|
|
||||||
@@ -614,7 +614,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (availableMission.ConnectionIndex < 0 || availableMission.ConnectionIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
if (availableMission.ConnectionIndex < 0 || availableMission.ConnectionIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.Identifier}\" out of range (index: {availableMission.ConnectionIndex}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.Identifier}\" out of range (index: {availableMission.ConnectionIndex}, current location: {campaign.Map.CurrentLocation.DisplayName}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.ConnectionIndex];
|
LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.ConnectionIndex];
|
||||||
@@ -647,7 +647,15 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (ownedSubIndex >= GameMain.Client.ServerSubmarines.Count)
|
if (ownedSubIndex >= GameMain.Client.ServerSubmarines.Count)
|
||||||
{
|
{
|
||||||
string errorMsg = $"Error in {nameof(MultiPlayerCampaign.ClientRead)}. Owned submarine index was out of bounds. Index: {ownedSubIndex}, submarines: {string.Join(", ", GameMain.Client.ServerSubmarines.Select(s => s.Name))}";
|
string errorMsg;
|
||||||
|
if (GameMain.Client.ServerSubmarines.None())
|
||||||
|
{
|
||||||
|
errorMsg = $"Error in {nameof(MultiPlayerCampaign.ClientRead)}. Owned submarine index was out of bounds (list of server submarines is empty).";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorMsg = $"Error in {nameof(MultiPlayerCampaign.ClientRead)}. Owned submarine index was out of bounds. Index: {ownedSubIndex}, submarines: {string.Join(", ", GameMain.Client.ServerSubmarines.Select(s => s.Name))}";
|
||||||
|
}
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg);
|
||||||
GameAnalyticsManager.AddErrorEventOnce(
|
GameAnalyticsManager.AddErrorEventOnce(
|
||||||
"MultiPlayerCampaign.ClientRead.OwnerSubIndexOutOfBounds" + ownedSubIndex,
|
"MultiPlayerCampaign.ClientRead.OwnerSubIndexOutOfBounds" + ownedSubIndex,
|
||||||
@@ -822,11 +830,12 @@ namespace Barotrauma
|
|||||||
UInt16 id = msg.ReadUInt16();
|
UInt16 id = msg.ReadUInt16();
|
||||||
bool hasCharacterData = msg.ReadBoolean();
|
bool hasCharacterData = msg.ReadBoolean();
|
||||||
CharacterInfo myCharacterInfo = null;
|
CharacterInfo myCharacterInfo = null;
|
||||||
|
bool waitForModsDownloaded = Screen.Selected is ModDownloadScreen;
|
||||||
if (hasCharacterData)
|
if (hasCharacterData)
|
||||||
{
|
{
|
||||||
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg, requireJobPrefabFound: !waitForModsDownloaded);
|
||||||
}
|
}
|
||||||
if (ShouldApply(NetFlags.CharacterInfo, id, requireUpToDateSave: true))
|
if (!waitForModsDownloaded && ShouldApply(NetFlags.CharacterInfo, id, requireUpToDateSave: true))
|
||||||
{
|
{
|
||||||
if (myCharacterInfo != null)
|
if (myCharacterInfo != null)
|
||||||
{
|
{
|
||||||
|
|||||||
+6
-3
@@ -548,9 +548,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//wasn't initially docked (sub doesn't have a docking port?)
|
//force the map to open if the sub is somehow not at the start of the outpost level
|
||||||
// -> choose a destination when the sub is far enough from the start outpost
|
//UNLESS the level has specific exit points, in that case the sub needs to get to those
|
||||||
if (!Submarine.MainSub.AtStartExit && !Level.Loaded.StartOutpost.ExitPoints.Any())
|
if (!Submarine.MainSub.AtStartExit &&
|
||||||
|
/*there should normally always be a start outpost in outpost levels,
|
||||||
|
* but that might not always be the case e.g. mods or outdated saves (see #13042)*/
|
||||||
|
Level.Loaded.StartOutpost is not { ExitPoints.Count: > 0 })
|
||||||
{
|
{
|
||||||
ForceMapUI = true;
|
ForceMapUI = true;
|
||||||
CampaignUI.SelectTab(InteractionType.Map);
|
CampaignUI.SelectTab(InteractionType.Map);
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private GUIImage eventLogNotification;
|
private GUIImage eventLogNotification;
|
||||||
|
|
||||||
|
private Point prevTopLeftButtonsResolution;
|
||||||
|
|
||||||
private void CreateTopLeftButtons()
|
private void CreateTopLeftButtons()
|
||||||
{
|
{
|
||||||
if (topLeftButtonGroup != null)
|
if (topLeftButtonGroup != null)
|
||||||
@@ -61,10 +63,6 @@ namespace Barotrauma
|
|||||||
AbsoluteSpacing = HUDLayoutSettings.Padding,
|
AbsoluteSpacing = HUDLayoutSettings.Padding,
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
topLeftButtonGroup.RectTransform.ParentChanged += (_) =>
|
|
||||||
{
|
|
||||||
GameMain.Instance.ResolutionChanged -= CreateTopLeftButtons;
|
|
||||||
};
|
|
||||||
int buttonHeight = GUI.IntScale(40);
|
int buttonHeight = GUI.IntScale(40);
|
||||||
Vector2 buttonSpriteSize = GUIStyle.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
|
Vector2 buttonSpriteSize = GUIStyle.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
|
||||||
int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X);
|
int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X);
|
||||||
@@ -98,8 +96,6 @@ namespace Barotrauma
|
|||||||
talentPointNotification = CreateNotificationIcon(tabMenuButton);
|
talentPointNotification = CreateNotificationIcon(tabMenuButton);
|
||||||
eventLogNotification = CreateNotificationIcon(tabMenuButton);
|
eventLogNotification = CreateNotificationIcon(tabMenuButton);
|
||||||
|
|
||||||
GameMain.Instance.ResolutionChanged += CreateTopLeftButtons;
|
|
||||||
|
|
||||||
respawnInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), parent: topLeftButtonGroup.RectTransform)
|
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)
|
{ MaxSize = new Point(HUDLayoutSettings.ButtonAreaTop.Width / 3, int.MaxValue) }, style: null)
|
||||||
{
|
{
|
||||||
@@ -121,6 +117,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
prevTopLeftButtonsResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
@@ -133,7 +130,8 @@ namespace Barotrauma
|
|||||||
if ((GameMode is not CampaignMode campaign || (!campaign.ForceMapUI && !campaign.ShowCampaignUI)) &&
|
if ((GameMode is not CampaignMode campaign || (!campaign.ForceMapUI && !campaign.ShowCampaignUI)) &&
|
||||||
!CoroutineManager.IsCoroutineRunning("LevelTransition") && !CoroutineManager.IsCoroutineRunning("SubmarineTransition"))
|
!CoroutineManager.IsCoroutineRunning("LevelTransition") && !CoroutineManager.IsCoroutineRunning("SubmarineTransition"))
|
||||||
{
|
{
|
||||||
if (topLeftButtonGroup == null)
|
if (topLeftButtonGroup == null ||
|
||||||
|
prevTopLeftButtonsResolution.X != GameMain.GraphicsWidth || prevTopLeftButtonsResolution.Y != GameMain.GraphicsHeight)
|
||||||
{
|
{
|
||||||
CreateTopLeftButtons();
|
CreateTopLeftButtons();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,11 @@ static class ObjectiveManager
|
|||||||
VideoPlayer.AddToGUIUpdateList(order: 100);
|
VideoPlayer.AddToGUIUpdateList(order: 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsSegmentActive(Identifier segmentId)
|
||||||
|
{
|
||||||
|
return activeObjectives.Any(o => o.Id == segmentId);
|
||||||
|
}
|
||||||
|
|
||||||
public static void TriggerSegment(Segment segment, bool connectObjective = false)
|
public static void TriggerSegment(Segment segment, bool connectObjective = false)
|
||||||
{
|
{
|
||||||
if (segment.SegmentType != SegmentType.InfoBox)
|
if (segment.SegmentType != SegmentType.InfoBox)
|
||||||
@@ -361,9 +366,18 @@ static class ObjectiveManager
|
|||||||
activeObjectives.IndexOf(parentSegment) + activeObjectives.Count(s => s.ParentId == segment.ParentId);
|
activeObjectives.IndexOf(parentSegment) + activeObjectives.Count(s => s.ParentId == segment.ParentId);
|
||||||
if (objectiveGroup.RectTransform.GetChildIndex(frameRt) != childIndex)
|
if (objectiveGroup.RectTransform.GetChildIndex(frameRt) != childIndex)
|
||||||
{
|
{
|
||||||
frameRt.RepositionChildInHierarchy(childIndex);
|
if (childIndex < 0 || childIndex >= frameRt.Parent.CountChildren)
|
||||||
activeObjectives.Remove(segment);
|
{
|
||||||
activeObjectives.Insert(childIndex, segment);
|
DebugConsole.ThrowError(
|
||||||
|
$"Error in {nameof(ObjectiveManager.AddToObjectiveList)}. " +
|
||||||
|
$"Failed to reposition an objective in the list. Text \"{segment.ObjectiveText}\", parentId: {segment.ParentId}, childIndex: {childIndex}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frameRt.RepositionChildInHierarchy(childIndex);
|
||||||
|
activeObjectives.Remove(segment);
|
||||||
|
activeObjectives.Insert(childIndex, segment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frameRt.AbsoluteOffset = GetObjectiveHiddenPosition();
|
frameRt.AbsoluteOffset = GetObjectiveHiddenPosition();
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private LocalizedString GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
private LocalizedString GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
|
||||||
{
|
{
|
||||||
string locationName = Submarine.MainSub is { AtEndExit: true } ? endLocation?.Name : startLocation?.Name;
|
LocalizedString locationName = Submarine.MainSub is { AtEndExit: true } ? endLocation?.DisplayName : startLocation?.DisplayName;
|
||||||
|
|
||||||
string textTag;
|
string textTag;
|
||||||
if (gameOver)
|
if (gameOver)
|
||||||
@@ -576,23 +576,23 @@ namespace Barotrauma
|
|||||||
switch (transitionType)
|
switch (transitionType)
|
||||||
{
|
{
|
||||||
case CampaignMode.TransitionType.LeaveLocation:
|
case CampaignMode.TransitionType.LeaveLocation:
|
||||||
locationName = startLocation?.Name;
|
locationName = startLocation?.DisplayName;
|
||||||
textTag = "RoundSummaryLeaving";
|
textTag = "RoundSummaryLeaving";
|
||||||
break;
|
break;
|
||||||
case CampaignMode.TransitionType.ProgressToNextLocation:
|
case CampaignMode.TransitionType.ProgressToNextLocation:
|
||||||
locationName = endLocation?.Name;
|
locationName = endLocation?.DisplayName;
|
||||||
textTag = "RoundSummaryProgress";
|
textTag = "RoundSummaryProgress";
|
||||||
break;
|
break;
|
||||||
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
||||||
locationName = endLocation?.Name;
|
locationName = endLocation?.DisplayName;
|
||||||
textTag = "RoundSummaryProgressToEmptyLocation";
|
textTag = "RoundSummaryProgressToEmptyLocation";
|
||||||
break;
|
break;
|
||||||
case CampaignMode.TransitionType.ReturnToPreviousLocation:
|
case CampaignMode.TransitionType.ReturnToPreviousLocation:
|
||||||
locationName = startLocation?.Name;
|
locationName = startLocation?.DisplayName;
|
||||||
textTag = "RoundSummaryReturn";
|
textTag = "RoundSummaryReturn";
|
||||||
break;
|
break;
|
||||||
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
||||||
locationName = startLocation?.Name;
|
locationName = startLocation?.DisplayName;
|
||||||
textTag = "RoundSummaryReturnToEmptyLocation";
|
textTag = "RoundSummaryReturnToEmptyLocation";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -603,14 +603,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (startLocation?.Biome != null && startLocation.Biome.IsEndBiome)
|
if (startLocation?.Biome != null && startLocation.Biome.IsEndBiome)
|
||||||
{
|
{
|
||||||
locationName ??= startLocation.Name;
|
locationName ??= startLocation.DisplayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textTag == null) { return ""; }
|
if (textTag == null) { return ""; }
|
||||||
|
|
||||||
if (locationName == null)
|
if (locationName == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Error while creating round summary: could not determine destination location. Start location: {startLocation?.Name ?? "null"}, end location: {endLocation?.Name ?? "null"}");
|
DebugConsole.ThrowError($"Error while creating round summary: could not determine destination location. Start location: {startLocation?.DisplayName ?? "null"}, end location: {endLocation?.DisplayName ?? "null"}");
|
||||||
locationName = "[UNKNOWN]";
|
locationName = "[UNKNOWN]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -568,7 +568,7 @@ namespace Barotrauma
|
|||||||
itemContainer.KeepOpenWhenEquippedBy(character) &&
|
itemContainer.KeepOpenWhenEquippedBy(character) &&
|
||||||
!DraggingItems.Contains(item) &&
|
!DraggingItems.Contains(item) &&
|
||||||
character.CanAccessInventory(itemContainer.Inventory) &&
|
character.CanAccessInventory(itemContainer.Inventory) &&
|
||||||
!highlightedSubInventorySlots.Any(s => s.Inventory == itemContainer.Inventory))
|
!highlightedSubInventorySlots.Any(s => s.Inventory == itemContainer.Inventory && s.SlotIndex == i))
|
||||||
{
|
{
|
||||||
ShowSubInventory(new SlotReference(this, visualSlots[i], i, false, itemContainer.Inventory), deltaTime, cam, hideSubInventories, true);
|
ShowSubInventory(new SlotReference(this, visualSlots[i], i, false, itemContainer.Inventory), deltaTime, cam, hideSubInventories, true);
|
||||||
}
|
}
|
||||||
@@ -709,11 +709,11 @@ namespace Barotrauma
|
|||||||
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List<SlotReference> hideSubInventories, bool isEquippedSubInventory)
|
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List<SlotReference> hideSubInventories, bool isEquippedSubInventory)
|
||||||
{
|
{
|
||||||
Rectangle hoverArea = GetSubInventoryHoverArea(slotRef);
|
Rectangle hoverArea = GetSubInventoryHoverArea(slotRef);
|
||||||
if (isEquippedSubInventory)
|
if (isEquippedSubInventory && slotRef.Inventory is not ItemInventory { Container.MovableFrame: true, Container.KeepOpenWhenEquipped: true })
|
||||||
{
|
{
|
||||||
foreach (SlotReference highlightedSubInventorySlot in highlightedSubInventorySlots)
|
foreach (SlotReference highlightedSubInventorySlot in highlightedSubInventorySlots)
|
||||||
{
|
{
|
||||||
if (highlightedSubInventorySlot == slotRef) continue;
|
if (highlightedSubInventorySlot == slotRef) { continue; }
|
||||||
if (hoverArea.Intersects(GetSubInventoryHoverArea(highlightedSubInventorySlot)))
|
if (hoverArea.Intersects(GetSubInventoryHoverArea(highlightedSubInventorySlot)))
|
||||||
{
|
{
|
||||||
return; // If an equipped one intersects with a currently active hover one, do not open
|
return; // If an equipped one intersects with a currently active hover one, do not open
|
||||||
@@ -818,7 +818,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (selectedContainer != null &&
|
if (selectedContainer != null &&
|
||||||
selectedContainer.Inventory != null &&
|
selectedContainer.Inventory != null &&
|
||||||
!selectedContainer.Inventory.Locked &&
|
!selectedContainer.Inventory.Locked &&
|
||||||
|
selectedContainer.DrawInventory &&
|
||||||
allowInventorySwap)
|
allowInventorySwap)
|
||||||
{
|
{
|
||||||
//player has selected the inventory of another item -> attempt to move the item there
|
//player has selected the inventory of another item -> attempt to move the item there
|
||||||
@@ -841,6 +842,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (character.HeldItems.FirstOrDefault(i =>
|
else if (character.HeldItems.FirstOrDefault(i =>
|
||||||
i.OwnInventory != null &&
|
i.OwnInventory != null &&
|
||||||
|
i.OwnInventory.Container.DrawInventory &&
|
||||||
(i.OwnInventory.CanBePut(item) || ((i.OwnInventory.Capacity == 1 || i.OwnInventory.Container.HasSubContainers) && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))) is { } equippedContainer)
|
(i.OwnInventory.CanBePut(item) || ((i.OwnInventory.Capacity == 1 || i.OwnInventory.Container.HasSubContainers) && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))) is { } equippedContainer)
|
||||||
{
|
{
|
||||||
if (allowEquip)
|
if (allowEquip)
|
||||||
@@ -1027,7 +1029,7 @@ namespace Barotrauma
|
|||||||
//order by the condition of the contained item to prefer putting into the item with the emptiest ammo/battery/tank
|
//order by the condition of the contained item to prefer putting into the item with the emptiest ammo/battery/tank
|
||||||
foreach (Item heldItem in character.HeldItems.OrderByDescending(heldItem => GetContainPriority(item, heldItem)))
|
foreach (Item heldItem in character.HeldItems.OrderByDescending(heldItem => GetContainPriority(item, heldItem)))
|
||||||
{
|
{
|
||||||
if (heldItem.OwnInventory == null) { continue; }
|
if (heldItem.OwnInventory == null || !heldItem.OwnInventory.Container.DrawInventory) { continue; }
|
||||||
//don't allow swapping if we're moving items into an item with 1 slot holding a stack of items
|
//don't allow swapping if we're moving items into an item with 1 slot holding a stack of items
|
||||||
//(in that case, the quick action should just fill up the stack)
|
//(in that case, the quick action should just fill up the stack)
|
||||||
bool disallowSwapping =
|
bool disallowSwapping =
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
||||||
{
|
{
|
||||||
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.Prefab == item.Prefab))
|
var otherGeneticMaterial =
|
||||||
|
deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item && it.Prefab == item.Prefab)?.GetComponent<GeneticMaterial>();
|
||||||
|
if (otherGeneticMaterial == null)
|
||||||
{
|
{
|
||||||
buttonText = TextManager.Get("researchstation.combine");
|
buttonText = TextManager.Get("researchstation.combine");
|
||||||
infoText = TextManager.Get("researchstation.combine.infotext");
|
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||||
@@ -62,7 +64,7 @@ namespace Barotrauma.Items.Components
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
buttonText = TextManager.Get("researchstation.refine");
|
buttonText = TextManager.Get("researchstation.refine");
|
||||||
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(Character.Controlled) * 100);
|
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(otherGeneticMaterial, Character.Controlled) * 100);
|
||||||
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
|
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,6 +260,12 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!hasSoundsOfType[(int)type]) { return; }
|
if (!hasSoundsOfType[(int)type]) { return; }
|
||||||
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
|
//above the top boundary of the level (in an inactive respawn shuttle?)
|
||||||
|
if (item.Submarine != null && Level.Loaded != null && item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (loopingSound != null)
|
if (loopingSound != null)
|
||||||
{
|
{
|
||||||
if (Vector3.DistanceSquared(GameMain.SoundManager.ListenerPosition, new Vector3(item.WorldPosition, 0.0f)) > loopingSound.Range * loopingSound.Range ||
|
if (Vector3.DistanceSquared(GameMain.SoundManager.ListenerPosition, new Vector3(item.WorldPosition, 0.0f)) > loopingSound.Range * loopingSound.Range ||
|
||||||
@@ -388,12 +394,9 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopSounds(ActionType type)
|
public void StopLoopingSound()
|
||||||
{
|
{
|
||||||
if (loopingSound == null) { return; }
|
if (loopingSound == null) { return; }
|
||||||
|
|
||||||
if (loopingSound.Type != type) { return; }
|
|
||||||
|
|
||||||
if (loopingSoundChannel != null)
|
if (loopingSoundChannel != null)
|
||||||
{
|
{
|
||||||
loopingSoundChannel.FadeOutAndDispose();
|
loopingSoundChannel.FadeOutAndDispose();
|
||||||
@@ -402,6 +405,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StopSounds(ActionType type)
|
||||||
|
{
|
||||||
|
if (loopingSound == null || loopingSound.Type != type) { return; }
|
||||||
|
StopLoopingSound();
|
||||||
|
}
|
||||||
|
|
||||||
private float GetSoundVolume(ItemSound sound)
|
private float GetSoundVolume(ItemSound sound)
|
||||||
{
|
{
|
||||||
if (sound == null) { return 0.0f; }
|
if (sound == null) { return 0.0f; }
|
||||||
@@ -497,7 +506,8 @@ namespace Barotrauma.Items.Components
|
|||||||
case "guiframe":
|
case "guiframe":
|
||||||
if (subElement.GetAttribute("rect") != null)
|
if (subElement.GetAttribute("rect") != null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Error in item config \"{item.ConfigFilePath}\" - GUIFrame defined as rect, use RectTransform instead.");
|
DebugConsole.ThrowError($"Error in item config \"{item.ConfigFilePath}\" - GUIFrame defined as rect, use RectTransform instead.",
|
||||||
|
contentPackage: subElement.ContentPackage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GuiFrameSource = subElement;
|
GuiFrameSource = subElement;
|
||||||
@@ -516,7 +526,8 @@ namespace Barotrauma.Items.Components
|
|||||||
if (filePath.IsNullOrEmpty())
|
if (filePath.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError(
|
DebugConsole.ThrowError(
|
||||||
$"Error when instantiating item \"{item.Name}\" - sound with no file path set");
|
$"Error when instantiating item \"{item.Name}\" - sound with no file path set",
|
||||||
|
contentPackage: subElement.ContentPackage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +539,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Invalid sound type \"{typeStr}\" in item \"{item.Prefab.Identifier}\"!", e);
|
DebugConsole.ThrowError($"Invalid sound type \"{typeStr}\" in item \"{item.Prefab.Identifier}\"!", e,
|
||||||
|
contentPackage: subElement.ContentPackage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,6 +770,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void OnPlayerSkillsChanged() { }
|
||||||
|
|
||||||
public virtual void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description) { }
|
public virtual void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ namespace Barotrauma.Items.Components
|
|||||||
IndicatorStyle = GUIStyle.GetComponentStyle("ContainedStateIndicator." + ContainedStateIndicatorStyle);
|
IndicatorStyle = GUIStyle.GetComponentStyle("ContainedStateIndicator." + ContainedStateIndicatorStyle);
|
||||||
if (ContainedStateIndicator != null || ContainedStateIndicatorEmpty != null)
|
if (ContainedStateIndicator != null || ContainedStateIndicatorEmpty != null)
|
||||||
{
|
{
|
||||||
DebugConsole.AddWarning($"Item \"{item.Name}\" defines both a contained state indicator style and a custom indicator sprite. Will use the custom sprite...");
|
DebugConsole.AddWarning($"Item \"{item.Name}\" defines both a contained state indicator style and a custom indicator sprite. Will use the custom sprite...",
|
||||||
|
contentPackage: item.Prefab.ContentPackage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GuiFrame == null)
|
if (GuiFrame == null)
|
||||||
@@ -345,9 +346,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public bool KeepOpenWhenEquippedBy(Character character)
|
public bool KeepOpenWhenEquippedBy(Character character)
|
||||||
{
|
{
|
||||||
if (!character.CanAccessInventory(Inventory) ||
|
if (!KeepOpenWhenEquipped ||
|
||||||
!KeepOpenWhenEquipped ||
|
!character.HasEquippedItem(Item) ||
|
||||||
!character.HasEquippedItem(Item))
|
!character.CanAccessInventory(Inventory))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -570,11 +571,13 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
spriteRotation = contained.Rotation;
|
spriteRotation = contained.Rotation;
|
||||||
}
|
}
|
||||||
if ((item.body != null && item.body.Dir == -1) || item.FlippedX)
|
bool flipX = (item.body != null && item.body.Dir == -1) || item.FlippedX;
|
||||||
|
if (flipX)
|
||||||
{
|
{
|
||||||
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
|
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
|
||||||
}
|
}
|
||||||
if (item.FlippedY)
|
bool flipY = item.FlippedY;
|
||||||
|
if (flipY)
|
||||||
{
|
{
|
||||||
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
||||||
}
|
}
|
||||||
@@ -588,6 +591,7 @@ namespace Barotrauma.Items.Components
|
|||||||
contained.Item.Scale,
|
contained.Item.Scale,
|
||||||
spriteEffects,
|
spriteEffects,
|
||||||
depth: containedSpriteDepth);
|
depth: containedSpriteDepth);
|
||||||
|
contained.Item.DrawDecorativeSprites(spriteBatch, itemPos, flipX,flipY, (contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation), containedSpriteDepth);
|
||||||
|
|
||||||
foreach (ItemContainer ic in contained.Item.GetComponents<ItemContainer>())
|
foreach (ItemContainer ic in contained.Item.GetComponents<ItemContainer>())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ namespace Barotrauma.Items.Components
|
|||||||
switch (text)
|
switch (text)
|
||||||
{
|
{
|
||||||
case "[CurrentLocationName]":
|
case "[CurrentLocationName]":
|
||||||
SetDisplayText(Level.Loaded?.StartLocation?.Name ?? string.Empty);
|
SetDisplayText(Level.Loaded?.StartLocation?.DisplayName.Value ?? string.Empty);
|
||||||
break;
|
break;
|
||||||
case "[CurrentBiomeName]":
|
case "[CurrentBiomeName]":
|
||||||
SetDisplayText(Level.Loaded?.LevelData?.Biome?.DisplayName.Value ?? string.Empty);
|
SetDisplayText(Level.Loaded?.LevelData?.Biome?.DisplayName.Value ?? string.Empty);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Light.Position = item.Position;
|
Light.Position = item.Position;
|
||||||
}
|
}
|
||||||
PhysicsBody body = Light.ParentBody;
|
PhysicsBody body = Light.ParentBody;
|
||||||
if (body != null)
|
if (body != null && body.Enabled)
|
||||||
{
|
{
|
||||||
Light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
|
Light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
|
||||||
Light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
Light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ namespace Barotrauma.Items.Components
|
|||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), sliderArea.RectTransform, Anchor.TopCenter), "", textColor: GUIStyle.TextColorNormal, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center)
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), sliderArea.RectTransform, Anchor.TopCenter), "", textColor: GUIStyle.TextColorNormal, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true,
|
AutoScaleHorizontal = true,
|
||||||
TextGetter = () => { return TextManager.AddPunctuation(':', powerLabel, (int)(targetForce) + " %"); }
|
TextGetter = () =>
|
||||||
|
{
|
||||||
|
return TextManager.AddPunctuation(':', powerLabel,
|
||||||
|
TextManager.GetWithVariable("percentageformat", "[value]", ((int)MathF.Round(targetForce)).ToString()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.95f, 0.45f), sliderArea.RectTransform, Anchor.Center), barSize: 0.1f, style: "DeviceSlider")
|
forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.95f, 0.45f), sliderArea.RectTransform, Anchor.Center), barSize: 0.1f, style: "DeviceSlider")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
@@ -393,6 +394,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
partial void SelectProjSpecific(Character character)
|
partial void SelectProjSpecific(Character character)
|
||||||
{
|
{
|
||||||
|
if (character != Character.Controlled) { return; }
|
||||||
|
|
||||||
var nonItems = itemList.Content.Children.Where(c => c.UserData is not FabricationRecipe).ToList();
|
var nonItems = itemList.Content.Children.Where(c => c.UserData is not FabricationRecipe).ToList();
|
||||||
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
|
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
|
||||||
|
|
||||||
@@ -784,6 +787,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void HideEmptyItemListCategories()
|
private void HideEmptyItemListCategories()
|
||||||
{
|
{
|
||||||
|
bool visibleElementsChanged = false;
|
||||||
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
|
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
|
||||||
bool recipeVisible = false;
|
bool recipeVisible = false;
|
||||||
foreach (GUIComponent child in itemList.Content.Children.Reverse())
|
foreach (GUIComponent child in itemList.Content.Children.Reverse())
|
||||||
@@ -792,7 +796,11 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (child.Enabled)
|
if (child.Enabled)
|
||||||
{
|
{
|
||||||
child.Visible = recipeVisible;
|
if (child.Visible != recipeVisible)
|
||||||
|
{
|
||||||
|
child.Visible = recipeVisible;
|
||||||
|
visibleElementsChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
recipeVisible = false;
|
recipeVisible = false;
|
||||||
}
|
}
|
||||||
@@ -802,8 +810,11 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemList.UpdateScrollBarSize();
|
if (visibleElementsChanged)
|
||||||
itemList.BarScroll = 0.0f;
|
{
|
||||||
|
itemList.UpdateScrollBarSize();
|
||||||
|
itemList.BarScroll = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ClearFilter()
|
public bool ClearFilter()
|
||||||
@@ -815,11 +826,22 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly record struct SelectedRecipe(Character User, FabricationRecipe SelectedItem, Option<float> OverrideRequiredTime);
|
||||||
|
private Option<SelectedRecipe> LastSelectedRecipe = Option.None;
|
||||||
|
|
||||||
private bool SelectItem(Character user, FabricationRecipe selectedItem, float? overrideRequiredTime = null)
|
private bool SelectItem(Character user, FabricationRecipe selectedItem, float? overrideRequiredTime = null)
|
||||||
{
|
{
|
||||||
this.selectedItem = selectedItem;
|
this.selectedItem = selectedItem;
|
||||||
displayingForCharacter = user;
|
displayingForCharacter = user;
|
||||||
|
var selectedRecipe = new SelectedRecipe(user, selectedItem, overrideRequiredTime is null ? Option.None : Option.Some(overrideRequiredTime.Value));
|
||||||
|
LastSelectedRecipe = Option.Some(selectedRecipe);
|
||||||
|
CreateSelectedItemUI(selectedRecipe);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateSelectedItemUI(SelectedRecipe recipe)
|
||||||
|
{
|
||||||
|
var (user, selectedItem, overrideRequiredTime) = recipe;
|
||||||
int max = Math.Max(selectedItem.TargetItem.GetMaxStackSize(outputContainer.Inventory) / selectedItem.Amount, 1);
|
int max = Math.Max(selectedItem.TargetItem.GetMaxStackSize(outputContainer.Inventory) / selectedItem.Amount, 1);
|
||||||
|
|
||||||
if (amountInput != null)
|
if (amountInput != null)
|
||||||
@@ -843,8 +865,10 @@ namespace Barotrauma.Items.Components
|
|||||||
LocalizedString itemName = GetRecipeNameAndAmount(selectedItem);
|
LocalizedString itemName = GetRecipeNameAndAmount(selectedItem);
|
||||||
LocalizedString name = itemName;
|
LocalizedString name = itemName;
|
||||||
|
|
||||||
float quality = selectedItem.Quality ?? GetFabricatedItemQuality(selectedItem, user);
|
QualityResult result = GetFabricatedItemQuality(selectedItem, user);
|
||||||
if (quality > 0)
|
|
||||||
|
float quality = selectedItem.Quality ?? result.Quality;
|
||||||
|
if (quality > 0 || result.HasRandomQualityRollChance)
|
||||||
{
|
{
|
||||||
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName + '\n')
|
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName + '\n')
|
||||||
.Fallback(TextManager.GetWithVariable("itemname.quality3", "[itemname]", itemName + '\n'));
|
.Fallback(TextManager.GetWithVariable("itemname.quality3", "[itemname]", itemName + '\n'));
|
||||||
@@ -855,6 +879,49 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
AutoScaleHorizontal = true
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (result.HasRandomQualityRollChance)
|
||||||
|
{
|
||||||
|
var iconLayout = new GUIFrame(new RectTransform(new Vector2(0.4f, 1f), selectedItemFrame.RectTransform, anchor: Anchor.TopRight), style: null);
|
||||||
|
var icon = GameSession.CreateNotificationIcon(iconLayout, offset: true);
|
||||||
|
|
||||||
|
float percentage1 = result.TotalPlusOnePercentage;
|
||||||
|
float percentage2 = result.TotalPlusTwoPercentage;
|
||||||
|
|
||||||
|
string chance1text = percentage1.ToString("F1", CultureInfo.InvariantCulture);
|
||||||
|
string chance2text = percentage2.ToString("F1", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
int quality1 = Math.Clamp(result.Quality + 1, min: 0, max: 3);
|
||||||
|
int quality2 = Math.Clamp(result.Quality + 2, min: 0, max: 3);
|
||||||
|
|
||||||
|
LocalizedString quality1Text = TextManager.Get($"quality{quality1}");
|
||||||
|
LocalizedString quality2Text = TextManager.Get($"quality{quality2}");
|
||||||
|
|
||||||
|
string localizationTag = percentage2 > 0f && percentage1 > 0 && quality1 != quality2 ? "meetsbonusrequirementtwice" : "meetsbonusrequirement";
|
||||||
|
|
||||||
|
var variables = new (string Key, LocalizedString Value)[]
|
||||||
|
{
|
||||||
|
("[chance]", chance1text), ("[quality]", quality1Text),
|
||||||
|
("[chance2]", chance2text), ("[quality2]", quality2Text)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (MathUtils.NearlyEqual(percentage1, 0))
|
||||||
|
{
|
||||||
|
variables = new[] { ("[chance]", chance2text), ("[quality]", quality2Text) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quality1 == quality2)
|
||||||
|
{
|
||||||
|
LocalizedString rawPercentage = result.PlusOnePercentage.ToString("F1", CultureInfo.InvariantCulture);
|
||||||
|
variables = new[] { ("[chance]", rawPercentage), ("[quality]", quality1Text) };
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalizedString qualityTooltip = TextManager.GetWithVariables(localizationTag, variables);
|
||||||
|
|
||||||
|
icon.ToolTip = RichString.Rich(qualityTooltip);
|
||||||
|
icon.Visible = icon.CanBeFocused = true;
|
||||||
|
}
|
||||||
|
|
||||||
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, GUI.IntScale(5), nameBlock.Padding.W);
|
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, GUI.IntScale(5), nameBlock.Padding.W);
|
||||||
if (nameBlock.TextScale < 0.7f)
|
if (nameBlock.TextScale < 0.7f)
|
||||||
{
|
{
|
||||||
@@ -865,15 +932,15 @@ namespace Barotrauma.Items.Components
|
|||||||
nameBlock.Wrap = true;
|
nameBlock.Wrap = true;
|
||||||
nameBlock.SetTextPos();
|
nameBlock.SetTextPos();
|
||||||
nameBlock.RectTransform.MinSize = new Point(0, (int)(nameBlock.TextSize.Y * nameBlock.TextScale));
|
nameBlock.RectTransform.MinSize = new Point(0, (int)(nameBlock.TextSize.Y * nameBlock.TextScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedItem.TargetItem.Description.IsNullOrEmpty())
|
if (!selectedItem.TargetItem.Description.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||||
selectedItem.TargetItem.Description,
|
selectedItem.TargetItem.Description,
|
||||||
font: GUIStyle.SmallFont, wrap: true);
|
font: GUIStyle.SmallFont, wrap: true);
|
||||||
description.Padding = new Vector4(0, description.Padding.Y, description.Padding.Z, description.Padding.W);
|
description.Padding = new Vector4(0, description.Padding.Y, description.Padding.Z, description.Padding.W);
|
||||||
|
|
||||||
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
||||||
{
|
{
|
||||||
var lines = description.WrappedText.Split('\n');
|
var lines = description.WrappedText.Split('\n');
|
||||||
@@ -884,13 +951,13 @@ namespace Barotrauma.Items.Components
|
|||||||
description.ToolTip = selectedItem.TargetItem.Description;
|
description.ToolTip = selectedItem.TargetItem.Description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Skill> inadequateSkills = Enumerable.Empty<Skill>();
|
IEnumerable<Skill> inadequateSkills = Enumerable.Empty<Skill>();
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
inadequateSkills = selectedItem.RequiredSkills.Where(skill => user.GetSkillLevel(skill.Identifier) < Math.Round(skill.Level * SkillRequirementMultiplier));
|
inadequateSkills = selectedItem.RequiredSkills.Where(skill => user.GetSkillLevel(skill.Identifier) < Math.Round(skill.Level * SkillRequirementMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedItem.RequiredSkills.Any())
|
if (selectedItem.RequiredSkills.Any())
|
||||||
{
|
{
|
||||||
LocalizedString text = "";
|
LocalizedString text = "";
|
||||||
@@ -911,9 +978,10 @@ namespace Barotrauma.Items.Components
|
|||||||
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
||||||
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
||||||
|
|
||||||
float requiredTime = overrideRequiredTime ??
|
float requiredTime = overrideRequiredTime.TryUnwrap(out var time)
|
||||||
(user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
|
? time
|
||||||
|
: (user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
|
||||||
|
|
||||||
if ((int)requiredTime > 0)
|
if ((int)requiredTime > 0)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||||
@@ -936,7 +1004,6 @@ namespace Barotrauma.Items.Components
|
|||||||
font: GUIStyle.SmallFont);
|
font: GUIStyle.SmallFont);
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HighlightRecipe(string identifier, Color color)
|
public void HighlightRecipe(string identifier, Color color)
|
||||||
@@ -1046,6 +1113,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnPlayerSkillsChanged()
|
||||||
|
=> RefreshSelectedItem();
|
||||||
|
|
||||||
|
public void RefreshSelectedItem()
|
||||||
|
{
|
||||||
|
if (!LastSelectedRecipe.TryUnwrap(out var lastSelected)) { return; }
|
||||||
|
CreateSelectedItemUI(lastSelected);
|
||||||
|
}
|
||||||
|
|
||||||
partial void UpdateRequiredTimeProjSpecific()
|
partial void UpdateRequiredTimeProjSpecific()
|
||||||
{
|
{
|
||||||
if (requiredTimeBlock == null) { return; }
|
if (requiredTimeBlock == null) { return; }
|
||||||
|
|||||||
@@ -66,7 +66,15 @@ namespace Barotrauma.Items.Components
|
|||||||
private float prevPassivePingRadius;
|
private float prevPassivePingRadius;
|
||||||
|
|
||||||
private Vector2 center;
|
private Vector2 center;
|
||||||
private float displayScale;
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current scale of the display, taking zoom into account. In other words, the scaling factor of world coordinates to coordinates on the display.
|
||||||
|
/// </summary>
|
||||||
|
public float DisplayScale
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
} = 1.0f;
|
||||||
|
|
||||||
private const float DisruptionUpdateInterval = 0.2f;
|
private const float DisruptionUpdateInterval = 0.2f;
|
||||||
private float disruptionUpdateTimer;
|
private float disruptionUpdateTimer;
|
||||||
@@ -751,9 +759,9 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
var activePing = activePings[pingIndex];
|
var activePing = activePings[pingIndex];
|
||||||
float pingRadius = DisplayRadius * activePing.State / zoom;
|
float pingRadius = DisplayRadius * activePing.State / zoom;
|
||||||
if (disruptionUpdateTimer <= 0.0f) { UpdateDisruptions(transducerCenter, pingRadius / displayScale); }
|
if (disruptionUpdateTimer <= 0.0f) { UpdateDisruptions(transducerCenter, pingRadius / DisplayScale); }
|
||||||
Ping(transducerCenter, transducerCenter,
|
Ping(transducerCenter, transducerCenter,
|
||||||
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)
|
||||||
@@ -770,7 +778,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (c.Params.HideInSonar) { continue; }
|
if (c.Params.HideInSonar) { continue; }
|
||||||
|
|
||||||
if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f &&
|
if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f &&
|
||||||
((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius)
|
((c.WorldPosition - transducerCenter) * DisplayScale).LengthSquared() > DisplayRadius * DisplayRadius)
|
||||||
{
|
{
|
||||||
Vector2 targetVector = c.WorldPosition - transducerCenter;
|
Vector2 targetVector = c.WorldPosition - transducerCenter;
|
||||||
if (targetVector.LengthSquared() > MathUtils.Pow2(c.Params.DistantSonarRange)) { continue; }
|
if (targetVector.LengthSquared() > MathUtils.Pow2(c.Params.DistantSonarRange)) { continue; }
|
||||||
@@ -818,7 +826,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (dist > prevPassivePingRadius * Range && dist <= passivePingRadius * Range && Rand.Int(sonarBlips.Count) < 500)
|
if (dist > prevPassivePingRadius * Range && dist <= passivePingRadius * Range && Rand.Int(sonarBlips.Count) < 500)
|
||||||
{
|
{
|
||||||
Ping(t.WorldPosition, transducerCenter,
|
Ping(t.WorldPosition, transducerCenter,
|
||||||
t.SoundRange * displayScale, 0, displayScale, range,
|
t.SoundRange * DisplayScale, 0, DisplayScale, range,
|
||||||
passive: true, pingStrength: 0.5f, needsToBeInSector: t);
|
passive: true, pingStrength: 0.5f, needsToBeInSector: t);
|
||||||
if (t.IsWithinSector(transducerCenter))
|
if (t.IsWithinSector(transducerCenter))
|
||||||
{
|
{
|
||||||
@@ -857,7 +865,7 @@ namespace Barotrauma.Items.Components
|
|||||||
displayBorderSize = 0.2f;
|
displayBorderSize = 0.2f;
|
||||||
center = rect.Center.ToVector2();
|
center = rect.Center.ToVector2();
|
||||||
DisplayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
|
DisplayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
|
||||||
displayScale = DisplayRadius / range * zoom;
|
DisplayScale = DisplayRadius / range * zoom;
|
||||||
|
|
||||||
screenBackground?.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
|
screenBackground?.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
|
||||||
|
|
||||||
@@ -972,7 +980,7 @@ namespace Barotrauma.Items.Components
|
|||||||
aiTarget.SonarIconIdentifier,
|
aiTarget.SonarIconIdentifier,
|
||||||
aiTarget,
|
aiTarget,
|
||||||
aiTarget.WorldPosition, transducerCenter,
|
aiTarget.WorldPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius * 0.975f);
|
DisplayScale, center, DisplayRadius * 0.975f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,21 +991,21 @@ namespace Barotrauma.Items.Components
|
|||||||
if (Level.Loaded.StartLocation?.Type is { ShowSonarMarker: true })
|
if (Level.Loaded.StartLocation?.Type is { ShowSonarMarker: true })
|
||||||
{
|
{
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
Level.Loaded.StartLocation.Name,
|
Level.Loaded.StartLocation.DisplayName.Value,
|
||||||
(Level.Loaded.StartOutpost != null ? "outpost" : "location").ToIdentifier(),
|
(Level.Loaded.StartOutpost != null ? "outpost" : "location").ToIdentifier(),
|
||||||
"startlocation",
|
"startlocation",
|
||||||
Level.Loaded.StartExitPosition, transducerCenter,
|
Level.Loaded.StartExitPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius);
|
DisplayScale, center, DisplayRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Level.Loaded is { EndLocation.Type.ShowSonarMarker: true, Type: LevelData.LevelType.LocationConnection })
|
if (Level.Loaded is { EndLocation.Type.ShowSonarMarker: true, Type: LevelData.LevelType.LocationConnection })
|
||||||
{
|
{
|
||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
Level.Loaded.EndLocation.Name,
|
Level.Loaded.EndLocation.DisplayName.Value,
|
||||||
(Level.Loaded.EndOutpost != null ? "outpost" : "location").ToIdentifier(),
|
(Level.Loaded.EndOutpost != null ? "outpost" : "location").ToIdentifier(),
|
||||||
"endlocation",
|
"endlocation",
|
||||||
Level.Loaded.EndExitPosition, transducerCenter,
|
Level.Loaded.EndExitPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius);
|
DisplayScale, center, DisplayRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Level.Loaded.Caves.Count; i++)
|
for (int i = 0; i < Level.Loaded.Caves.Count; i++)
|
||||||
@@ -1009,7 +1017,7 @@ namespace Barotrauma.Items.Components
|
|||||||
"cave".ToIdentifier(),
|
"cave".ToIdentifier(),
|
||||||
"cave" + i,
|
"cave" + i,
|
||||||
cave.StartPos.ToVector2(), transducerCenter,
|
cave.StartPos.ToVector2(), transducerCenter,
|
||||||
displayScale, center, DisplayRadius);
|
DisplayScale, center, DisplayRadius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1026,7 +1034,7 @@ namespace Barotrauma.Items.Components
|
|||||||
mission.SonarIconIdentifier,
|
mission.SonarIconIdentifier,
|
||||||
"mission" + missionIndex + ":" + i,
|
"mission" + missionIndex + ":" + i,
|
||||||
position, transducerCenter,
|
position, transducerCenter,
|
||||||
displayScale, center, DisplayRadius * 0.95f);
|
DisplayScale, center, DisplayRadius * 0.95f);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1059,7 +1067,7 @@ namespace Barotrauma.Items.Components
|
|||||||
DrawMarker(spriteBatch,
|
DrawMarker(spriteBatch,
|
||||||
i.Name, "mineral".ToIdentifier(), "mineralcluster" + i,
|
i.Name, "mineral".ToIdentifier(), "mineralcluster" + i,
|
||||||
c.center, transducerCenter,
|
c.center, transducerCenter,
|
||||||
displayScale, center, DisplayRadius * 0.95f,
|
DisplayScale, center, DisplayRadius * 0.95f,
|
||||||
onlyShowTextOnMouseOver: true);
|
onlyShowTextOnMouseOver: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1088,19 +1096,19 @@ namespace Barotrauma.Items.Components
|
|||||||
(sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine").ToIdentifier(),
|
(sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine").ToIdentifier(),
|
||||||
sub,
|
sub,
|
||||||
sub.WorldPosition, transducerCenter,
|
sub.WorldPosition, transducerCenter,
|
||||||
displayScale, center, DisplayRadius * 0.95f);
|
DisplayScale, center, DisplayRadius * 0.95f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
var steering = item.GetComponent<Steering>();
|
var steering = item.GetComponent<Steering>();
|
||||||
steering?.DebugDrawHUD(spriteBatch, transducerCenter, displayScale, DisplayRadius, center);
|
steering?.DebugDrawHUD(spriteBatch, transducerCenter, DisplayScale, DisplayRadius, center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawOwnSubmarineBorders(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
|
private void DrawOwnSubmarineBorders(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
|
||||||
{
|
{
|
||||||
float simScale = displayScale * Physics.DisplayToSimRation * zoom;
|
float simScale = DisplayScale * Physics.DisplayToSimRation;
|
||||||
|
|
||||||
foreach (Submarine submarine in Submarine.Loaded)
|
foreach (Submarine submarine in Submarine.Loaded)
|
||||||
{
|
{
|
||||||
@@ -1167,7 +1175,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void DrawDockingPorts(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
|
private void DrawDockingPorts(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
|
||||||
{
|
{
|
||||||
float scale = displayScale * zoom;
|
float scale = DisplayScale;
|
||||||
|
|
||||||
Steering steering = item.GetComponent<Steering>();
|
Steering steering = item.GetComponent<Steering>();
|
||||||
if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null)
|
if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null)
|
||||||
@@ -1219,7 +1227,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private void DrawDockingIndicator(SpriteBatch spriteBatch, Steering steering, ref Vector2 transducerCenter)
|
private void DrawDockingIndicator(SpriteBatch spriteBatch, Steering steering, ref Vector2 transducerCenter)
|
||||||
{
|
{
|
||||||
float scale = displayScale * zoom;
|
float scale = DisplayScale;
|
||||||
|
|
||||||
Vector2 worldFocusPos = (steering.ActiveDockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f;
|
Vector2 worldFocusPos = (steering.ActiveDockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f;
|
||||||
worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X;
|
worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X;
|
||||||
@@ -1591,7 +1599,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
lineStep /= zoom;
|
lineStep /= zoom;
|
||||||
zStep /= zoom;
|
zStep /= zoom;
|
||||||
range *= displayScale;
|
range *= DisplayScale;
|
||||||
float length = (point1 - point2).Length();
|
float length = (point1 - point2).Length();
|
||||||
Vector2 lineDir = (point2 - point1) / length;
|
Vector2 lineDir = (point2 - point1) / length;
|
||||||
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
|
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
|
||||||
@@ -1602,12 +1610,12 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
//ignore if outside the display
|
//ignore if outside the display
|
||||||
Vector2 transducerDiff = point - transducerPos;
|
Vector2 transducerDiff = point - transducerPos;
|
||||||
Vector2 transducerDisplayDiff = transducerDiff * displayScale;
|
Vector2 transducerDisplayDiff = transducerDiff * DisplayScale / zoom;
|
||||||
if (transducerDisplayDiff.LengthSquared() > DisplayRadius * DisplayRadius) { continue; }
|
if (transducerDisplayDiff.LengthSquared() > DisplayRadius * DisplayRadius) { continue; }
|
||||||
|
|
||||||
//ignore if the point is not within the ping
|
//ignore if the point is not within the ping
|
||||||
Vector2 pointDiff = point - pingSource;
|
Vector2 pointDiff = point - pingSource;
|
||||||
Vector2 displayPointDiff = pointDiff * displayScale;
|
Vector2 displayPointDiff = pointDiff * DisplayScale / zoom;
|
||||||
float displayPointDistSqr = displayPointDiff.LengthSquared();
|
float displayPointDistSqr = displayPointDiff.LengthSquared();
|
||||||
if (displayPointDistSqr < prevPingRadius * prevPingRadius || displayPointDistSqr > pingRadius * pingRadius) { continue; }
|
if (displayPointDistSqr < prevPingRadius * prevPingRadius || displayPointDistSqr > pingRadius * pingRadius) { continue; }
|
||||||
|
|
||||||
@@ -1628,9 +1636,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
float displayPointDist = (float)Math.Sqrt(displayPointDistSqr);
|
float displayPointDist = (float)Math.Sqrt(displayPointDistSqr);
|
||||||
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
|
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
|
||||||
for (float z = 0; z < DisplayRadius - transducerDist * displayScale; z += zStep)
|
for (float z = 0; z < DisplayRadius - transducerDist * DisplayScale; z += zStep)
|
||||||
{
|
{
|
||||||
Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / displayScale;
|
Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / DisplayScale;
|
||||||
float fadeTimer = alpha * (1.0f - displayPointDist / range);
|
float fadeTimer = alpha * (1.0f - displayPointDist / range);
|
||||||
|
|
||||||
if (needsToBeInSector != null)
|
if (needsToBeInSector != null)
|
||||||
@@ -1697,7 +1705,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private bool CheckBlipVisibility(SonarBlip blip, Vector2 transducerPos)
|
private bool CheckBlipVisibility(SonarBlip blip, Vector2 transducerPos)
|
||||||
{
|
{
|
||||||
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
|
Vector2 pos = (blip.Position - transducerPos) * DisplayScale;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
float posDistSqr = pos.LengthSquared();
|
float posDistSqr = pos.LengthSquared();
|
||||||
@@ -1731,7 +1739,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
if (currentPingIndex != -1 && activePings[currentPingIndex].IsDirectional)
|
if (currentPingIndex != -1 && activePings[currentPingIndex].IsDirectional)
|
||||||
{
|
{
|
||||||
var pos = (resourcePos - transducerPos) * displayScale * zoom;
|
var pos = (resourcePos - transducerPos) * DisplayScale;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
var length = pos.Length();
|
var length = pos.Length();
|
||||||
var dir = pos / length;
|
var dir = pos / length;
|
||||||
@@ -1749,7 +1757,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
float distort = 1.0f - item.Condition / item.MaxCondition;
|
float distort = 1.0f - item.Condition / item.MaxCondition;
|
||||||
|
|
||||||
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
|
Vector2 pos = (blip.Position - transducerPos) * DisplayScale;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
if (Rand.Range(0.5f, 2.0f) < distort) { pos.X = -pos.X; }
|
if (Rand.Range(0.5f, 2.0f) < distort) { pos.X = -pos.X; }
|
||||||
@@ -1825,14 +1833,13 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Vector2 position = worldPosition - transducerPosition;
|
Vector2 position = worldPosition - transducerPosition;
|
||||||
|
|
||||||
position *= zoom;
|
|
||||||
position *= scale;
|
position *= scale;
|
||||||
position.Y = -position.Y;
|
position.Y = -position.Y;
|
||||||
|
|
||||||
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
|
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
|
||||||
|
|
||||||
Vector2 dir = Vector2.Normalize(position);
|
Vector2 dir = Vector2.Normalize(position);
|
||||||
Vector2 markerPos = (linearDist * zoom * scale > radius) ? dir * radius : position;
|
Vector2 markerPos = (linearDist * scale > radius) ? dir * radius : position;
|
||||||
markerPos += center;
|
markerPos += center;
|
||||||
|
|
||||||
markerPos.X = (int)markerPos.X;
|
markerPos.X = (int)markerPos.X;
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.Center),
|
levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.Center),
|
||||||
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, GUIStyle.SmallFont, textLimit),
|
GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.DisplayName, GUIStyle.SmallFont, textLimit),
|
||||||
font: GUIStyle.SmallFont, style: "GUIRadioButton")
|
font: GUIStyle.SmallFont, style: "GUIRadioButton")
|
||||||
{
|
{
|
||||||
Enabled = autoPilot,
|
Enabled = autoPilot,
|
||||||
@@ -243,7 +243,7 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
|
|
||||||
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.BottomCenter),
|
levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.333f), paddedAutoPilotControls.RectTransform, Anchor.BottomCenter),
|
||||||
(GameMain.GameSession?.EndLocation == null || Level.IsLoadedOutpost) ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, GUIStyle.SmallFont, textLimit),
|
(GameMain.GameSession?.EndLocation == null || Level.IsLoadedOutpost) ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.DisplayName, GUIStyle.SmallFont, textLimit),
|
||||||
font: GUIStyle.SmallFont, style: "GUIRadioButton")
|
font: GUIStyle.SmallFont, style: "GUIRadioButton")
|
||||||
{
|
{
|
||||||
Enabled = autoPilot,
|
Enabled = autoPilot,
|
||||||
@@ -389,7 +389,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (!ObjectiveManager.AllActiveObjectivesCompleted())
|
if (!ObjectiveManager.AllActiveObjectivesCompleted())
|
||||||
{
|
{
|
||||||
exitOutpostPrompt = new GUIMessageBox("",
|
exitOutpostPrompt = new GUIMessageBox("",
|
||||||
TextManager.GetWithVariable("CampaignExitTutorialOutpostPrompt", "[locationname]", campaign.Map.CurrentLocation.Name),
|
TextManager.GetWithVariable("CampaignExitTutorialOutpostPrompt", "[locationname]", campaign.Map.CurrentLocation.DisplayName),
|
||||||
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
|
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
exitOutpostPrompt.Buttons[0].OnClicked += (_, _) =>
|
exitOutpostPrompt.Buttons[0].OnClicked += (_, _) =>
|
||||||
{
|
{
|
||||||
@@ -509,9 +509,9 @@ namespace Barotrauma.Items.Components
|
|||||||
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
noPowerTip = TextManager.Get("SteeringNoPowerTip");
|
||||||
autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip");
|
autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip");
|
||||||
autoPilotLevelStartTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]",
|
autoPilotLevelStartTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]",
|
||||||
GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.Name);
|
GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.DisplayName);
|
||||||
autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]",
|
autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]",
|
||||||
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name);
|
GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.DisplayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResolutionChanged()
|
protected override void OnResolutionChanged()
|
||||||
@@ -589,7 +589,8 @@ namespace Barotrauma.Items.Components
|
|||||||
Sonar sonar = item.GetComponent<Sonar>();
|
Sonar sonar = item.GetComponent<Sonar>();
|
||||||
if (sonar != null && controlledSub != null)
|
if (sonar != null && controlledSub != null)
|
||||||
{
|
{
|
||||||
Vector2 displayPosToMaintain = ((posToMaintain.Value - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
|
Vector2 displayPosToMaintain = ((posToMaintain.Value - controlledSub.WorldPosition)) * sonar.DisplayScale;
|
||||||
|
|
||||||
displayPosToMaintain.Y = -displayPosToMaintain.Y;
|
displayPosToMaintain.Y = -displayPosToMaintain.Y;
|
||||||
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
|
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
|
||||||
displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain;
|
displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain;
|
||||||
@@ -670,14 +671,14 @@ namespace Barotrauma.Items.Components
|
|||||||
pos2.Y = -pos2.Y;
|
pos2.Y = -pos2.Y;
|
||||||
pos2 += center;
|
pos2 += center;
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
pos1,
|
pos1,
|
||||||
pos2,
|
pos2,
|
||||||
GUIStyle.Red * 0.6f, width: 3);
|
GUIStyle.Red * 0.6f, width: 3);
|
||||||
|
|
||||||
if (obstacle.Intersection.HasValue)
|
if (obstacle.Intersection.HasValue)
|
||||||
{
|
{
|
||||||
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) *displayScale;
|
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) * displayScale;
|
||||||
intersectionPos.Y = -intersectionPos.Y;
|
intersectionPos.Y = -intersectionPos.Y;
|
||||||
intersectionPos += center;
|
intersectionPos += center;
|
||||||
GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, GUIStyle.Red);
|
GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, GUIStyle.Red);
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ namespace Barotrauma.Items.Components
|
|||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
|
new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
|
||||||
new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
|
new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
|
||||||
Color.Yellow);
|
Color.Yellow, width: 3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace Barotrauma.Items.Components
|
|||||||
MaxValueFloat = numberInputMax,
|
MaxValueFloat = numberInputMax,
|
||||||
FloatValue = Math.Clamp(floatSignal, numberInputMin, numberInputMax),
|
FloatValue = Math.Clamp(floatSignal, numberInputMin, numberInputMax),
|
||||||
DecimalsToDisplay = ciElement.NumberInputDecimalPlaces,
|
DecimalsToDisplay = ciElement.NumberInputDecimalPlaces,
|
||||||
valueStep = numberInputStep,
|
ValueStep = numberInputStep,
|
||||||
OnValueChanged = (ni) =>
|
OnValueChanged = (ni) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
@@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components
|
|||||||
MinValueInt = numberInputMin,
|
MinValueInt = numberInputMin,
|
||||||
MaxValueInt = numberInputMax,
|
MaxValueInt = numberInputMax,
|
||||||
IntValue = Math.Clamp(intSignal, numberInputMin, numberInputMax),
|
IntValue = Math.Clamp(intSignal, numberInputMin, numberInputMax),
|
||||||
valueStep = numberInputStep,
|
ValueStep = numberInputStep,
|
||||||
OnValueChanged = (ni) =>
|
OnValueChanged = (ni) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
@@ -137,7 +137,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"");
|
DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"",
|
||||||
|
contentPackage: item.Prefab.ContentPackage);
|
||||||
}
|
}
|
||||||
if (numberInput != null)
|
if (numberInput != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -349,8 +349,8 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUI.DrawString(spriteBatch, hudPos, texts[0].Value, textColors[0] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
|
GUI.DrawString(spriteBatch, hudPos, texts[0].Value, textColors[0] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
|
||||||
hudPos.X += 5.0f;
|
hudPos.X += 5.0f * GUI.Scale;
|
||||||
hudPos.Y += 24.0f * GameSettings.CurrentConfig.Graphics.TextScale;
|
hudPos.Y += GUIStyle.SubHeadingFont.MeasureString(texts[0].Value).Y;
|
||||||
|
|
||||||
hudPos.X = (int)hudPos.X;
|
hudPos.X = (int)hudPos.X;
|
||||||
hudPos.Y = (int)hudPos.Y;
|
hudPos.Y = (int)hudPos.Y;
|
||||||
@@ -358,7 +358,7 @@ namespace Barotrauma.Items.Components
|
|||||||
for (int i = 1; i < texts.Count; i++)
|
for (int i = 1; i < texts.Count; i++)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SmallFont);
|
GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SmallFont);
|
||||||
hudPos.Y += (int)(18.0f * GameSettings.CurrentConfig.Graphics.TextScale);
|
hudPos.Y += (int)(GUIStyle.SubHeadingFont.MeasureString(texts[i].Value).Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private GUIProgressBar powerIndicator;
|
private GUIProgressBar powerIndicator;
|
||||||
|
|
||||||
|
private Vector2? debugDrawTargetPos;
|
||||||
|
|
||||||
public int UIElementHeight
|
public int UIElementHeight
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -422,9 +424,23 @@ namespace Barotrauma.Items.Components
|
|||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
Vector2 firingPos = GetRelativeFiringPosition();
|
Vector2 firingPos = GetRelativeFiringPosition();
|
||||||
|
Vector2 endPos = firingPos + 3500 * GetBarrelDir();
|
||||||
firingPos.Y = -firingPos.Y;
|
firingPos.Y = -firingPos.Y;
|
||||||
|
endPos.Y = -endPos.Y;
|
||||||
GUI.DrawLine(spriteBatch, firingPos - Vector2.UnitX * 5, firingPos + Vector2.UnitX * 5, Color.Red);
|
GUI.DrawLine(spriteBatch, firingPos - Vector2.UnitX * 5, firingPos + Vector2.UnitX * 5, Color.Red);
|
||||||
GUI.DrawLine(spriteBatch, firingPos - Vector2.UnitY * 5, firingPos + Vector2.UnitY * 5, Color.Red);
|
GUI.DrawLine(spriteBatch, firingPos - Vector2.UnitY * 5, firingPos + Vector2.UnitY * 5, Color.Red);
|
||||||
|
|
||||||
|
if (debugDrawTargetPos.HasValue)
|
||||||
|
{
|
||||||
|
Vector2 targetPos = debugDrawTargetPos.Value;
|
||||||
|
targetPos.Y = -targetPos.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, targetPos - Vector2.UnitX * 5, targetPos + Vector2.UnitX * 5, Color.Magenta, width: 5);
|
||||||
|
GUI.DrawLine(spriteBatch, targetPos - Vector2.UnitY * 5, targetPos + Vector2.UnitY * 5, Color.Magenta, width: 5);
|
||||||
|
|
||||||
|
GUI.DrawLine(spriteBatch, firingPos, targetPos, Color.Magenta, width: 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
GUI.DrawLine(spriteBatch, firingPos, endPos, Color.LightGray, width: 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!editing || GUI.DisableHUD || !item.IsSelected) { return; }
|
if (!editing || GUI.DisableHUD || !item.IsSelected) { return; }
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LocalizedString description = item.Description;
|
LocalizedString description = item.Description;
|
||||||
if (item.HasTag(Tags.IdCard) || item.HasTag(Tags.DespawnContainer))
|
if (item.HasTag(Tags.IdCardTag) || item.HasTag(Tags.DespawnContainer))
|
||||||
{
|
{
|
||||||
string[] readTags = item.Tags.Split(',');
|
string[] readTags = item.Tags.Split(',');
|
||||||
string idName = null;
|
string idName = null;
|
||||||
@@ -730,7 +730,7 @@ namespace Barotrauma
|
|||||||
DraggingInventory = null;
|
DraggingInventory = null;
|
||||||
subInventory.savedPosition = PlayerInput.MousePosition.ToPoint();
|
subInventory.savedPosition = PlayerInput.MousePosition.ToPoint();
|
||||||
}
|
}
|
||||||
else
|
else if (DraggingInventory == subInventory)
|
||||||
{
|
{
|
||||||
subInventory.savedPosition = PlayerInput.MousePosition.ToPoint();
|
subInventory.savedPosition = PlayerInput.MousePosition.ToPoint();
|
||||||
}
|
}
|
||||||
@@ -901,7 +901,7 @@ namespace Barotrauma
|
|||||||
if (IsOnInventorySlot(Character.Controlled.SelectedCharacter.Inventory)) { return true; }
|
if (IsOnInventorySlot(Character.Controlled.SelectedCharacter.Inventory)) { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsOnInventorySlot(Inventory inventory)
|
static bool IsOnInventorySlot(Inventory inventory)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < inventory.visualSlots.Length; i++)
|
for (var i = 0; i < inventory.visualSlots.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -1107,7 +1107,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (container.MovableFrame && !IsInventoryHoverAvailable(Owner as Character, container))
|
if (container.MovableFrame && !IsInventoryHoverAvailable(Owner as Character, container))
|
||||||
{
|
{
|
||||||
if (positionUpdateQueued) // Wait a frame before updating the positioning of the container after a resolution change to have everything working
|
if (container.Inventory.positionUpdateQueued) // Wait a frame before updating the positioning of the container after a resolution change to have everything working
|
||||||
{
|
{
|
||||||
int height = (int)(movableFrameRectHeight * UIScale);
|
int height = (int)(movableFrameRectHeight * UIScale);
|
||||||
CreateSlots();
|
CreateSlots();
|
||||||
@@ -1116,7 +1116,7 @@ namespace Barotrauma
|
|||||||
draggableIndicatorOffset = DraggableIndicator.size * draggableIndicatorScale / 2f;
|
draggableIndicatorOffset = DraggableIndicator.size * draggableIndicatorScale / 2f;
|
||||||
draggableIndicatorOffset += new Vector2(height / 2f - draggableIndicatorOffset.Y);
|
draggableIndicatorOffset += new Vector2(height / 2f - draggableIndicatorOffset.Y);
|
||||||
container.Inventory.originalPos = container.Inventory.savedPosition = container.Inventory.movableFrameRect.Center;
|
container.Inventory.originalPos = container.Inventory.savedPosition = container.Inventory.movableFrameRect.Center;
|
||||||
positionUpdateQueued = false;
|
container.Inventory.positionUpdateQueued = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container.Inventory.movableFrameRect.Size == Point.Zero || GUI.HasSizeChanged(prevScreenResolution, prevUIScale, prevHUDScale))
|
if (container.Inventory.movableFrameRect.Size == Point.Zero || GUI.HasSizeChanged(prevScreenResolution, prevUIScale, prevHUDScale))
|
||||||
@@ -1127,11 +1127,20 @@ namespace Barotrauma
|
|||||||
prevScreenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
prevScreenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||||
prevUIScale = UIScale;
|
prevUIScale = UIScale;
|
||||||
prevHUDScale = GUI.Scale;
|
prevHUDScale = GUI.Scale;
|
||||||
positionUpdateQueued = true;
|
container.Inventory.positionUpdateQueued = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, container.Inventory.movableFrameRect, movableFrameRectColor, true);
|
Color color = movableFrameRectColor;
|
||||||
|
if (DraggingInventory != null && DraggingInventory != container.Inventory)
|
||||||
|
{
|
||||||
|
color *= 0.7f;
|
||||||
|
}
|
||||||
|
else if (container.Inventory.movableFrameRect.Contains(PlayerInput.MousePosition))
|
||||||
|
{
|
||||||
|
color = Color.Lerp(color, PlayerInput.PrimaryMouseButtonHeld() ? Color.Black : Color.White, 0.25f);
|
||||||
|
}
|
||||||
|
GUI.DrawRectangle(spriteBatch, container.Inventory.movableFrameRect, color, true);
|
||||||
DraggableIndicator.Draw(spriteBatch, container.Inventory.movableFrameRect.Location.ToVector2() + draggableIndicatorOffset, 0, draggableIndicatorScale);
|
DraggableIndicator.Draw(spriteBatch, container.Inventory.movableFrameRect.Location.ToVector2() + draggableIndicatorOffset, 0, draggableIndicatorScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,12 +1278,20 @@ namespace Barotrauma
|
|||||||
if (DraggingItems.Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1 ||
|
if (DraggingItems.Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1 ||
|
||||||
selectedInventory.GetItemsAt(slotIndex).Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1)
|
selectedInventory.GetItemsAt(slotIndex).Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1)
|
||||||
{
|
{
|
||||||
allowCombine = false;
|
allowCombine = false;
|
||||||
}
|
}
|
||||||
int itemCount = 0;
|
int itemCount = 0;
|
||||||
foreach (Item item in DraggingItems)
|
foreach (Item item in DraggingItems)
|
||||||
{
|
{
|
||||||
bool success = selectedInventory.TryPutItem(item, slotIndex, allowSwapping: !anySuccess, allowCombine, Character.Controlled);
|
if (selectedInventory.GetItemAt(slotIndex)?.OwnInventory?.Container is { } container &&
|
||||||
|
container.Inventory.CanBePut(item))
|
||||||
|
{
|
||||||
|
if (!container.AllowDragAndDrop || !container.DrawInventory)
|
||||||
|
{
|
||||||
|
allowCombine = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool success = selectedInventory.TryPutItem(item, slotIndex, allowSwapping: !anySuccess, allowCombine, Character.Controlled);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
anySuccess = true;
|
anySuccess = true;
|
||||||
@@ -1380,18 +1397,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
protected static Rectangle GetSubInventoryHoverArea(SlotReference subSlot)
|
||||||
{
|
{
|
||||||
Rectangle hoverArea;
|
if (Character.Controlled == null)
|
||||||
if ((Screen.Selected != GameMain.SubEditorScreen || GameMain.SubEditorScreen.DrawCharacterInventory) &&
|
|
||||||
(!subSlot.Inventory.Movable() ||
|
|
||||||
(Character.Controlled?.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item)) ||
|
|
||||||
(subSlot.ParentInventory is CharacterInventory characterInventory && characterInventory.CurrentLayout != CharacterInventory.Layout.Default)))
|
|
||||||
{
|
{
|
||||||
//slot not visible as a separate, movable panel -> just use the area of the slot directly
|
return Rectangle.Empty;
|
||||||
hoverArea = subSlot.Slot.Rect;
|
|
||||||
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
|
||||||
hoverArea = Rectangle.Union(hoverArea, subSlot.Slot.EquipButtonRect);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
Rectangle hoverArea;
|
||||||
|
bool isMovable = subSlot.Inventory.Movable() && !subSlot.ParentInventory.IsInventoryHoverAvailable(Character.Controlled, subSlot.Item?.GetComponent<ItemContainer>());
|
||||||
|
bool unEquipped = Character.Controlled.Inventory == subSlot.ParentInventory && !Character.Controlled.HasEquippedItem(subSlot.Item);
|
||||||
|
bool isDefaultLayout = subSlot.ParentInventory is not CharacterInventory characterInventory || characterInventory.CurrentLayout == CharacterInventory.Layout.Default;
|
||||||
|
bool subEditorCharacterInventoryHidden = Screen.Selected == GameMain.SubEditorScreen && !GameMain.SubEditorScreen.DrawCharacterInventory;
|
||||||
|
if (subEditorCharacterInventoryHidden || (isMovable && !unEquipped && isDefaultLayout))
|
||||||
{
|
{
|
||||||
hoverArea = subSlot.Inventory.BackgroundFrame;
|
hoverArea = subSlot.Inventory.BackgroundFrame;
|
||||||
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
||||||
@@ -1400,6 +1416,13 @@ namespace Barotrauma
|
|||||||
hoverArea = Rectangle.Union(hoverArea, subSlot.Inventory.movableFrameRect);
|
hoverArea = Rectangle.Union(hoverArea, subSlot.Inventory.movableFrameRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//slot not visible as a separate, movable panel -> just use the area of the slot directly
|
||||||
|
hoverArea = subSlot.Slot.Rect;
|
||||||
|
hoverArea.Location += subSlot.Slot.DrawOffset.ToPoint();
|
||||||
|
hoverArea = Rectangle.Union(hoverArea, subSlot.Slot.EquipButtonRect);
|
||||||
|
}
|
||||||
|
|
||||||
if (subSlot.Inventory?.visualSlots != null)
|
if (subSlot.Inventory?.visualSlots != null)
|
||||||
{
|
{
|
||||||
@@ -1584,11 +1607,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (DraggingItems.Any() && inventory != null && slotIndex > -1 && slotIndex < inventory.visualSlots.Length)
|
if (DraggingItems.Any() && inventory != null && slotIndex > -1 && slotIndex < inventory.visualSlots.Length)
|
||||||
{
|
{
|
||||||
|
var itemInSlot = inventory.slots[slotIndex].FirstOrDefault();
|
||||||
if (inventory.CanBePutInSlot(DraggingItems.First(), slotIndex))
|
if (inventory.CanBePutInSlot(DraggingItems.First(), slotIndex))
|
||||||
{
|
{
|
||||||
canBePut = true;
|
canBePut = true;
|
||||||
}
|
}
|
||||||
else if (inventory.slots[slotIndex].FirstOrDefault()?.OwnInventory?.CanBePut(DraggingItems.First()) ?? false)
|
else if
|
||||||
|
(itemInSlot?.OwnInventory != null &&
|
||||||
|
itemInSlot.OwnInventory.CanBePut(DraggingItems.First()) &&
|
||||||
|
itemInSlot.OwnInventory.Container.AllowDragAndDrop &&
|
||||||
|
itemInSlot.OwnInventory.Container.DrawInventory)
|
||||||
{
|
{
|
||||||
canBePut = true;
|
canBePut = true;
|
||||||
}
|
}
|
||||||
@@ -1922,9 +1950,25 @@ namespace Barotrauma
|
|||||||
foreach (UInt16 id in receivedItemIDs[i])
|
foreach (UInt16 id in receivedItemIDs[i])
|
||||||
{
|
{
|
||||||
if (Entity.FindEntityByID(id) is not Item item || slots[i].Contains(item)) { continue; }
|
if (Entity.FindEntityByID(id) is not Item item || slots[i].Contains(item)) { continue; }
|
||||||
|
|
||||||
|
if (Owner is Item thisItem && thisItem.Container == item)
|
||||||
|
{
|
||||||
|
//if this item is inside the item we're trying to contain inside it, we need to drop it (both items can't be inside each other!)
|
||||||
|
//can happen when a player swaps the items to be "the other way around", and we receive a message about the contained item
|
||||||
|
//before the message about the "parent item" being placed in some other inventory (like the player's inventory)
|
||||||
|
thisItem.Drop(null);
|
||||||
|
}
|
||||||
|
|
||||||
if (!TryPutItem(item, i, false, false, null, false))
|
if (!TryPutItem(item, i, false, false, null, false))
|
||||||
{
|
{
|
||||||
ForceToSlot(item, i);
|
try
|
||||||
|
{
|
||||||
|
ForceToSlot(item, i);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException e)
|
||||||
|
{
|
||||||
|
DebugConsole.AddSafeError(e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int j = 0; j < capacity; j++)
|
for (int j = 0; j < capacity; j++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ namespace Barotrauma
|
|||||||
return GetDrawDepth(SpriteDepth + DrawDepthOffset, Sprite);
|
return GetDrawDepth(SpriteDepth + DrawDepthOffset, Sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color GetSpriteColor(bool withHighlight = false)
|
public Color GetSpriteColor(Color? defaultColor = null, bool withHighlight = false)
|
||||||
{
|
{
|
||||||
Color color = spriteColor;
|
Color color = defaultColor ?? spriteColor;
|
||||||
if (Prefab.UseContainedSpriteColor && ownInventory != null)
|
if (Prefab.UseContainedSpriteColor && ownInventory != null)
|
||||||
{
|
{
|
||||||
foreach (Item item in ContainedItems)
|
foreach (Item item in ContainedItems)
|
||||||
@@ -286,7 +286,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
int padding = 100;
|
int padding = 100;
|
||||||
|
|
||||||
Vector2 min = new Vector2(-rect.Width / 2 - padding, -rect.Height / 2 - padding);
|
RectangleF boundingBox = GetTransformedQuad().BoundingAxisAlignedRectangle;
|
||||||
|
Vector2 min = new Vector2(-boundingBox.Width / 2 - padding, -boundingBox.Height / 2 - padding);
|
||||||
Vector2 max = -min;
|
Vector2 max = -min;
|
||||||
|
|
||||||
foreach (IDrawableComponent drawable in drawableComponents)
|
foreach (IDrawableComponent drawable in drawableComponents)
|
||||||
@@ -333,9 +334,7 @@ namespace Barotrauma
|
|||||||
else if (!ShowItems) { return; }
|
else if (!ShowItems) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
Color color =
|
Color color = GetSpriteColor(spriteColor);
|
||||||
overrideColor ??
|
|
||||||
(IsIncludedInSelection && editing ? GUIStyle.Blue : GetSpriteColor(withHighlight: true));
|
|
||||||
|
|
||||||
bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null;
|
bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null;
|
||||||
bool renderTransparent = isWiringMode && GetComponent<ConnectionPanel>() == null;
|
bool renderTransparent = isWiringMode && GetComponent<ConnectionPanel>() == null;
|
||||||
@@ -388,9 +387,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (Prefab.ResizeHorizontal || Prefab.ResizeVertical)
|
if (Prefab.ResizeHorizontal || Prefab.ResizeVertical)
|
||||||
{
|
{
|
||||||
Vector2 size = new Vector2(rect.Width, rect.Height);
|
|
||||||
if (color.A > 0)
|
if (color.A > 0)
|
||||||
{
|
{
|
||||||
|
Vector2 size = new Vector2(rect.Width, rect.Height);
|
||||||
activeSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + drawOffset,
|
activeSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)) + drawOffset,
|
||||||
size, color: color,
|
size, color: color,
|
||||||
textureScale: Vector2.One * Scale,
|
textureScale: Vector2.One * Scale,
|
||||||
@@ -403,18 +402,7 @@ namespace Barotrauma
|
|||||||
textureScale: Vector2.One * Scale,
|
textureScale: Vector2.One * Scale,
|
||||||
depth: d);
|
depth: d);
|
||||||
}
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, rotation: 0, depth);
|
||||||
{
|
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? RotationRad : -RotationRad) * Scale;
|
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
|
||||||
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
|
||||||
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
|
||||||
size, color: color,
|
|
||||||
textureScale: Vector2.One * Scale,
|
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -434,19 +422,8 @@ namespace Barotrauma
|
|||||||
Prefab.InfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, Prefab.InfectedSprite.Origin, RotationRad, Scale, activeSprite.effects, depth - 0.001f);
|
Prefab.InfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, Prefab.InfectedSprite.Origin, RotationRad, Scale, activeSprite.effects, depth - 0.001f);
|
||||||
Prefab.DamagedInfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, Infector.HealthColor, Prefab.DamagedInfectedSprite.Origin, RotationRad, Scale, activeSprite.effects, depth - 0.002f);
|
Prefab.DamagedInfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, Infector.HealthColor, Prefab.DamagedInfectedSprite.Origin, RotationRad, Scale, activeSprite.effects, depth - 0.002f);
|
||||||
}
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
|
||||||
{
|
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, -RotationRad, depth);
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
|
||||||
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
|
||||||
bool flipX = flippedX && Prefab.CanSpriteFlipX;
|
|
||||||
bool flipY = flippedY && Prefab.CanSpriteFlipY;
|
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flipX ^ flipY ? RotationRad : -RotationRad) * Scale;
|
|
||||||
if (flipX) { offset.X = -offset.X; }
|
|
||||||
if (flipY) { offset.Y = -offset.Y; }
|
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
|
||||||
RotationRad + rot, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
|
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (body.Enabled)
|
else if (body.Enabled)
|
||||||
@@ -490,21 +467,7 @@ namespace Barotrauma
|
|||||||
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
|
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
|
||||||
body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, d, Scale);
|
body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, d, Scale);
|
||||||
}
|
}
|
||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
DrawDecorativeSprites(spriteBatch, body.DrawPosition, flipX: body.Dir < 0, flipY: false, rotation: body.Rotation, depth: depth);
|
||||||
{
|
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -RotationRad) * Scale;
|
|
||||||
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
|
|
||||||
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
|
|
||||||
var ca = MathF.Cos(-body.DrawRotation);
|
|
||||||
var sa = MathF.Sin(-body.DrawRotation);
|
|
||||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
|
||||||
|
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), color,
|
|
||||||
-body.DrawRotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
|
|
||||||
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var upgrade in Upgrades)
|
foreach (var upgrade in Upgrades)
|
||||||
@@ -522,7 +485,6 @@ namespace Barotrauma
|
|||||||
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
|
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
|
||||||
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activeSprite.effects = oldEffects;
|
activeSprite.effects = oldEffects;
|
||||||
@@ -567,8 +529,14 @@ namespace Barotrauma
|
|||||||
Vector2 drawPos = new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2));
|
Vector2 drawPos = new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2));
|
||||||
Vector2 drawSize = new Vector2(MathF.Ceiling(rect.Width + Math.Abs(drawPos.X - (int)drawPos.X)), MathF.Ceiling(rect.Height + Math.Abs(drawPos.Y - (int)drawPos.Y)));
|
Vector2 drawSize = new Vector2(MathF.Ceiling(rect.Width + Math.Abs(drawPos.X - (int)drawPos.X)), MathF.Ceiling(rect.Height + Math.Abs(drawPos.Y - (int)drawPos.Y)));
|
||||||
drawPos = new Vector2(MathF.Floor(drawPos.X), MathF.Floor(drawPos.Y));
|
drawPos = new Vector2(MathF.Floor(drawPos.X), MathF.Floor(drawPos.Y));
|
||||||
GUI.DrawRectangle(spriteBatch, drawPos, drawSize,
|
GUI.DrawRectangle(sb: spriteBatch,
|
||||||
Color.White, false, 0, thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
|
center: drawPos + drawSize * 0.5f,
|
||||||
|
width: drawSize.X,
|
||||||
|
height: drawSize.Y,
|
||||||
|
rotation: RotationRad,
|
||||||
|
clr: Color.White,
|
||||||
|
depth: 0,
|
||||||
|
thickness: 2f / Screen.Selected.Cam.Zoom);
|
||||||
|
|
||||||
foreach (Rectangle t in Prefab.Triggers)
|
foreach (Rectangle t in Prefab.Triggers)
|
||||||
{
|
{
|
||||||
@@ -618,6 +586,62 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color GetSpriteColor(Color defaultColor)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
overrideColor ??
|
||||||
|
(IsIncludedInSelection && editing ? GUIStyle.Blue : this.GetSpriteColor(defaultColor: defaultColor, withHighlight: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawDecorativeSprites(SpriteBatch spriteBatch, Vector2 drawPos, bool flipX, bool flipY, float rotation, float depth)
|
||||||
|
{
|
||||||
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
|
{
|
||||||
|
Color decorativeSpriteColor = GetSpriteColor(decorativeSprite.Color).Multiply(GetSpriteColor(spriteColor));
|
||||||
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
|
|
||||||
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier,
|
||||||
|
flipX ^ flipY ? -rotation : rotation) * Scale;
|
||||||
|
|
||||||
|
if (ResizeHorizontal || ResizeVertical)
|
||||||
|
{
|
||||||
|
decorativeSprite.Sprite.DrawTiled(spriteBatch,
|
||||||
|
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
|
||||||
|
new Vector2(rect.Width, rect.Height), color: decorativeSpriteColor,
|
||||||
|
textureScale: Vector2.One * Scale,
|
||||||
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float spriteRotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
||||||
|
|
||||||
|
Vector2 origin = decorativeSprite.Sprite.Origin;
|
||||||
|
SpriteEffects spriteEffects = SpriteEffects.None;
|
||||||
|
if (flipX && Prefab.CanSpriteFlipX)
|
||||||
|
{
|
||||||
|
offset.X = -offset.X;
|
||||||
|
origin.X = -origin.X + decorativeSprite.Sprite.size.X;
|
||||||
|
spriteEffects = SpriteEffects.FlipHorizontally;
|
||||||
|
}
|
||||||
|
if (flipY && Prefab.CanSpriteFlipY)
|
||||||
|
{
|
||||||
|
offset.Y = -offset.Y;
|
||||||
|
origin.Y = -origin.Y + decorativeSprite.Sprite.size.Y;
|
||||||
|
spriteEffects |= SpriteEffects.FlipVertically;
|
||||||
|
}
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
var ca = MathF.Cos(-body.DrawRotation);
|
||||||
|
var sa = MathF.Sin(-body.DrawRotation);
|
||||||
|
offset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||||
|
}
|
||||||
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(drawPos.X + offset.X, -(drawPos.Y + offset.Y)), decorativeSpriteColor, origin,
|
||||||
|
-rotation + spriteRotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffects,
|
||||||
|
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnCollisionProjSpecific(float impact)
|
partial void OnCollisionProjSpecific(float impact)
|
||||||
@@ -795,6 +819,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsMouseOn(Vector2 position)
|
||||||
|
{
|
||||||
|
Vector2 rectSize = rect.Size.ToVector2();
|
||||||
|
|
||||||
|
Vector2 bodyPos = WorldPosition;
|
||||||
|
|
||||||
|
Vector2 transformedMousePos = MathUtils.RotatePointAroundTarget(position, bodyPos, RotationRad);
|
||||||
|
|
||||||
|
return
|
||||||
|
Math.Abs(transformedMousePos.X - bodyPos.X) < rectSize.X / 2.0f &&
|
||||||
|
Math.Abs(transformedMousePos.Y - bodyPos.Y) < rectSize.Y / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
public GUIComponent CreateEditingHUD(bool inGame = false)
|
public GUIComponent CreateEditingHUD(bool inGame = false)
|
||||||
{
|
{
|
||||||
activeEditors.Clear();
|
activeEditors.Clear();
|
||||||
@@ -852,7 +889,12 @@ namespace Barotrauma
|
|||||||
CanBeFocused = true
|
CanBeFocused = true
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
GUINumberInput rotationField =
|
||||||
|
itemEditor.Fields.TryGetValue("Rotation".ToIdentifier(), out var rotationFieldComponents)
|
||||||
|
? rotationFieldComponents.OfType<GUINumberInput>().FirstOrDefault()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
var mirrorX = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
||||||
Enabled = Prefab.CanFlipX,
|
Enabled = Prefab.CanFlipX,
|
||||||
@@ -863,10 +905,13 @@ namespace Barotrauma
|
|||||||
me.FlipX(relativeToSub: false);
|
me.FlipX(relativeToSub: false);
|
||||||
}
|
}
|
||||||
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
|
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
|
||||||
|
ColorFlipButton(button, FlippedX);
|
||||||
|
if (rotationField != null) { rotationField.FloatValue = Rotation; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
ColorFlipButton(mirrorX, FlippedX);
|
||||||
|
var mirrorY = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
||||||
Enabled = Prefab.CanFlipY,
|
Enabled = Prefab.CanFlipY,
|
||||||
@@ -877,9 +922,12 @@ namespace Barotrauma
|
|||||||
me.FlipY(relativeToSub: false);
|
me.FlipY(relativeToSub: false);
|
||||||
}
|
}
|
||||||
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
|
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
|
||||||
|
ColorFlipButton(button, FlippedY);
|
||||||
|
if (rotationField != null) { rotationField.FloatValue = Rotation; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
ColorFlipButton(mirrorY, FlippedY);
|
||||||
if (Sprite != null)
|
if (Sprite != null)
|
||||||
{
|
{
|
||||||
var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall");
|
var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall");
|
||||||
@@ -1540,6 +1588,23 @@ namespace Barotrauma
|
|||||||
RemoveFromDroppedStack(allowClientExecute: true);
|
RemoveFromDroppedStack(allowClientExecute: true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EventType.SetHighlight:
|
||||||
|
bool isTargetedForThisClient = msg.ReadBoolean();
|
||||||
|
if (isTargetedForThisClient)
|
||||||
|
{
|
||||||
|
bool highlight = msg.ReadBoolean();
|
||||||
|
ExternalHighlight = highlight;
|
||||||
|
if (highlight)
|
||||||
|
{
|
||||||
|
Color highlightColor = msg.ReadColorR8G8B8A8();
|
||||||
|
HighlightColor = highlightColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HighlightColor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Malformed incoming item event: unsupported event type {eventType}");
|
throw new Exception($"Malformed incoming item event: unsupported event type {eventType}");
|
||||||
}
|
}
|
||||||
@@ -1940,5 +2005,13 @@ namespace Barotrauma
|
|||||||
Inventory.DraggingSlot = null;
|
Inventory.DraggingSlot = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnPlayerSkillsChanged()
|
||||||
|
{
|
||||||
|
foreach (ItemComponent ic in components)
|
||||||
|
{
|
||||||
|
ic.OnPlayerSkillsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,10 +321,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ResizeHorizontal)
|
if (ResizeHorizontal) { placeSize.X = Math.Max(position.X - placePosition.X, Size.X); }
|
||||||
placeSize.X = Math.Max(position.X - placePosition.X, Size.X);
|
if (ResizeVertical) { placeSize.Y = Math.Max(placePosition.Y - position.Y, Size.Y); }
|
||||||
if (ResizeVertical)
|
|
||||||
placeSize.Y = Math.Max(placePosition.Y - position.Y, Size.Y);
|
|
||||||
|
|
||||||
if (PlayerInput.PrimaryMouseButtonReleased())
|
if (PlayerInput.PrimaryMouseButtonReleased())
|
||||||
{
|
{
|
||||||
@@ -369,15 +367,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||||
{
|
{
|
||||||
if (!ResizeHorizontal && !ResizeVertical)
|
if (!ResizeHorizontal && !ResizeVertical)
|
||||||
{
|
{
|
||||||
Sprite.Draw(spriteBatch, new Vector2(placeRect.Center.X, -(placeRect.Y - placeRect.Height / 2)), SpriteColor * 0.8f, scale: scale);
|
sprite.Draw(
|
||||||
|
spriteBatch: spriteBatch,
|
||||||
|
pos: new Vector2(placeRect.Center.X,
|
||||||
|
-(placeRect.Y - placeRect.Height / 2)),
|
||||||
|
color: SpriteColor * 0.8f,
|
||||||
|
scale: scale,
|
||||||
|
rotate: rotation,
|
||||||
|
spriteEffect: spriteEffects ^ sprite.effects);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sprite.DrawTiled(spriteBatch, new Vector2(placeRect.X, -placeRect.Y), placeRect.Size.ToVector2(), SpriteColor * 0.8f);
|
Vector2 position = placeRect.Location.ToVector2();
|
||||||
|
Vector2 placeSize = placeRect.Size.ToVector2();
|
||||||
|
sprite?.DrawTiled(
|
||||||
|
spriteBatch: spriteBatch,
|
||||||
|
position: new Vector2(position.X, -position.Y),
|
||||||
|
targetSize: placeSize,
|
||||||
|
rotation: rotation,
|
||||||
|
textureScale: Vector2.One * scale,
|
||||||
|
color: SpriteColor * 0.8f,
|
||||||
|
spriteEffects: spriteEffects ^ sprite.effects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -277,12 +277,21 @@ namespace Barotrauma
|
|||||||
Rectangle drawRect =
|
Rectangle drawRect =
|
||||||
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
|
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
|
||||||
|
|
||||||
if ((IsSelected || IsHighlighted) && editing)
|
if (editing)
|
||||||
{
|
{
|
||||||
|
if (IsSelected || IsHighlighted)
|
||||||
|
{
|
||||||
|
GUI.DrawRectangle(spriteBatch,
|
||||||
|
new Vector2(drawRect.X, -drawRect.Y),
|
||||||
|
new Vector2(rect.Width, rect.Height),
|
||||||
|
(IsHighlighted ? Color.LightBlue * 0.8f : GUIStyle.Red * 0.5f) * alpha, false, 0, (int)Math.Max(5.0f / Screen.Selected.Cam.Zoom, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
float waterHeight = WaterVolume / rect.Width;
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Vector2(drawRect.X, -drawRect.Y),
|
new Vector2(drawRect.X, -drawRect.Y + drawRect.Height - waterHeight),
|
||||||
new Vector2(rect.Width, rect.Height),
|
new Vector2(drawRect.Width, waterHeight),
|
||||||
(IsHighlighted ? Color.LightBlue * 0.8f : GUIStyle.Red * 0.5f) * alpha, false, 0, (int)Math.Max(5.0f / Screen.Selected.Cam.Zoom, 1.0f));
|
Color.Blue * 0.25f, isFilled: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
@@ -746,7 +755,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var newFire = i < FireSources.Count ?
|
var newFire = i < FireSources.Count ?
|
||||||
FireSources[i] :
|
FireSources[i] :
|
||||||
new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
|
new FireSource(Submarine == null ? pos : pos + Submarine.Position, sourceCharacter: null, isNetworkMessage: true);
|
||||||
newFire.Position = pos;
|
newFire.Position = pos;
|
||||||
newFire.Size = new Vector2(size, newFire.Size.Y);
|
newFire.Size = new Vector2(size, newFire.Size.Y);
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace Barotrauma
|
|||||||
MathUtils.RoundTowardsClosest(center.Y, Submarine.GridSize.Y) - center.Y - Submarine.GridSize.Y / 2);
|
MathUtils.RoundTowardsClosest(center.Y, Submarine.GridSize.Y) - center.Y - Submarine.GridSize.Y / 2);
|
||||||
|
|
||||||
MapEntity.SelectedList.Clear();
|
MapEntity.SelectedList.Clear();
|
||||||
assemblyEntities.ForEach(e => MapEntity.AddSelection(e));
|
entities.ForEach(e => MapEntity.AddSelection(e));
|
||||||
|
|
||||||
foreach (MapEntity mapEntity in assemblyEntities)
|
foreach (MapEntity mapEntity in assemblyEntities)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
mainElement = mainElement.FirstElement();
|
mainElement = mainElement.FirstElement();
|
||||||
prefabs.Clear();
|
prefabs.Clear();
|
||||||
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.Yellow);
|
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.MediumPurple);
|
||||||
}
|
}
|
||||||
else if (prefabs.Any())
|
else if (prefabs.Any())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
using FarseerPhysics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FarseerPhysics;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -53,7 +52,7 @@ namespace Barotrauma
|
|||||||
foreach (InterestingPosition pos in PositionsOfInterest)
|
foreach (InterestingPosition pos in PositionsOfInterest)
|
||||||
{
|
{
|
||||||
Color color = Color.Yellow;
|
Color color = Color.Yellow;
|
||||||
if (pos.PositionType == PositionType.Cave)
|
if (pos.PositionType == PositionType.Cave || pos.PositionType == PositionType.AbyssCave)
|
||||||
{
|
{
|
||||||
color = Color.DarkOrange;
|
color = Color.DarkOrange;
|
||||||
}
|
}
|
||||||
@@ -61,6 +60,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
color = Color.LightGray;
|
color = Color.LightGray;
|
||||||
}
|
}
|
||||||
|
if (!pos.IsValid)
|
||||||
|
{
|
||||||
|
color = Color.Red;
|
||||||
|
}
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,8 @@ namespace Barotrauma
|
|||||||
CanBeVisible =
|
CanBeVisible =
|
||||||
Sprite != null ||
|
Sprite != null ||
|
||||||
Prefab.DeformableSprite != null ||
|
Prefab.DeformableSprite != null ||
|
||||||
|
ParticleEmitters is { Length: > 0 } ||
|
||||||
|
(GameMain.DebugDraw && Triggers is { Count: > 0 }) ||
|
||||||
Prefab.OverrideProperties.Any(p => p != null && (p.Sprites.Any() || p.DeformableSprite != null));
|
Prefab.OverrideProperties.Any(p => p != null && (p.Sprites.Any() || p.DeformableSprite != null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -23,7 +23,14 @@ namespace Barotrauma
|
|||||||
private Rectangle currentGridIndices;
|
private Rectangle currentGridIndices;
|
||||||
|
|
||||||
public bool ForceRefreshVisibleObjects;
|
public bool ForceRefreshVisibleObjects;
|
||||||
|
|
||||||
|
partial void RemoveProjSpecific()
|
||||||
|
{
|
||||||
|
visibleObjectsBack.Clear();
|
||||||
|
visibleObjectsMid.Clear();
|
||||||
|
visibleObjectsFront.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
partial void UpdateProjSpecific(float deltaTime)
|
partial void UpdateProjSpecific(float deltaTime)
|
||||||
{
|
{
|
||||||
foreach (LevelObject obj in visibleObjectsBack)
|
foreach (LevelObject obj in visibleObjectsBack)
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
public Rectangle BoundingBox { get; private set; }
|
public Rectangle BoundingBox { get; private set; }
|
||||||
|
|
||||||
|
public bool IsInvalid { get; private set; }
|
||||||
|
|
||||||
public ConvexHull(Rectangle rect, bool isHorizontal, MapEntity parent)
|
public ConvexHull(Rectangle rect, bool isHorizontal, MapEntity parent)
|
||||||
{
|
{
|
||||||
shadowEffect ??= new BasicEffect(GameMain.Instance.GraphicsDevice)
|
shadowEffect ??= new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||||
@@ -481,15 +483,34 @@ namespace Barotrauma.Lights
|
|||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
vertices[i].WorldPos = vertices[i].Pos;
|
vertices[i].WorldPos = vertices[i].Pos;
|
||||||
|
ValidateVertex(vertices[i].WorldPos, "vertices[i].Pos");
|
||||||
segments[i].Start.WorldPos = segments[i].Start.Pos;
|
segments[i].Start.WorldPos = segments[i].Start.Pos;
|
||||||
|
ValidateVertex(segments[i].Start.WorldPos, "segments[i].Start.Pos");
|
||||||
segments[i].End.WorldPos = segments[i].End.Pos;
|
segments[i].End.WorldPos = segments[i].End.Pos;
|
||||||
|
ValidateVertex(segments[i].End.WorldPos, "segments[i].End.Pos");
|
||||||
}
|
}
|
||||||
if (ParentEntity == null || ParentEntity.Submarine == null) { return; }
|
if (ParentEntity == null || ParentEntity.Submarine == null) { return; }
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
vertices[i].WorldPos += ParentEntity.Submarine.DrawPosition;
|
vertices[i].WorldPos += ParentEntity.Submarine.DrawPosition;
|
||||||
|
ValidateVertex(vertices[i].WorldPos, "vertices[i].WorldPos");
|
||||||
segments[i].Start.WorldPos += ParentEntity.Submarine.DrawPosition;
|
segments[i].Start.WorldPos += ParentEntity.Submarine.DrawPosition;
|
||||||
|
ValidateVertex(segments[i].Start.WorldPos, "segments[i].Start.WorldPos");
|
||||||
segments[i].End.WorldPos += ParentEntity.Submarine.DrawPosition;
|
segments[i].End.WorldPos += ParentEntity.Submarine.DrawPosition;
|
||||||
|
ValidateVertex(segments[i].End.WorldPos, "segments[i].End.WorldPos");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateVertex(Vector2 vertex, string debugName)
|
||||||
|
{
|
||||||
|
if (!MathUtils.IsValid(vertex))
|
||||||
|
{
|
||||||
|
IsInvalid = true;
|
||||||
|
string errorMsg = $"Invalid vertex on convex hull ({debugName}: {vertex}, parent entity: {ParentEntity?.ToString() ?? "null"}).";
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError(errorMsg);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("ConvexHull.RefreshWorldPositions:InvalidVertex", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,15 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DebugDrawVertices(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
foreach (LightSource light in lights)
|
||||||
|
{
|
||||||
|
if (!light.Enabled) { continue; }
|
||||||
|
light.DebugDrawVertices(spriteBatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
||||||
{
|
{
|
||||||
if (!LightingEnabled) { return; }
|
if (!LightingEnabled) { return; }
|
||||||
@@ -269,6 +278,9 @@ namespace Barotrauma.Lights
|
|||||||
light.Position = pos;
|
light.Position = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//above the top boundary of the level (in an inactive respawn shuttle?)
|
||||||
|
if (Level.Loaded != null && light.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||||
|
|
||||||
float range = light.LightSourceParams.TextureRange;
|
float range = light.LightSourceParams.TextureRange;
|
||||||
if (light.LightSprite != null)
|
if (light.LightSprite != null)
|
||||||
{
|
{
|
||||||
@@ -801,6 +813,8 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
public void ClearLights()
|
public void ClearLights()
|
||||||
{
|
{
|
||||||
|
activeLights.Clear();
|
||||||
|
activeLightsWithLightVolume.Clear();
|
||||||
lights.Clear();
|
lights.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ namespace Barotrauma.Lights
|
|||||||
TextureRange = range;
|
TextureRange = range;
|
||||||
if (OverrideLightTexture != null)
|
if (OverrideLightTexture != null)
|
||||||
{
|
{
|
||||||
TextureRange += Math.Max(
|
TextureRange *= 1.0f + Math.Max(
|
||||||
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f) * OverrideLightTexture.size.X,
|
Math.Abs(OverrideLightTexture.RelativeOrigin.X - 0.5f),
|
||||||
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f) * OverrideLightTexture.size.Y);
|
Math.Abs(OverrideLightTexture.RelativeOrigin.Y - 0.5f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,11 @@ namespace Barotrauma.Lights
|
|||||||
private bool needsRecalculationWhenUpToDate;
|
private bool needsRecalculationWhenUpToDate;
|
||||||
public bool NeedsRecalculation
|
public bool NeedsRecalculation
|
||||||
{
|
{
|
||||||
get { return needsRecalculation; }
|
get
|
||||||
|
{
|
||||||
|
if (ParentBody?.UserData is Item it && it.Prefab.Identifier == "flashlight") { return true; }
|
||||||
|
return needsRecalculation;
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!needsRecalculation && value)
|
if (!needsRecalculation && value)
|
||||||
@@ -708,6 +712,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
foreach (ConvexHull hull in chList.List)
|
foreach (ConvexHull hull in chList.List)
|
||||||
{
|
{
|
||||||
|
if (hull.IsInvalid) { continue; }
|
||||||
if (!chList.IsHidden.Contains(hull))
|
if (!chList.IsHidden.Contains(hull))
|
||||||
{
|
{
|
||||||
//find convexhull segments that are close enough and facing towards the light source
|
//find convexhull segments that are close enough and facing towards the light source
|
||||||
@@ -735,6 +740,7 @@ namespace Barotrauma.Lights
|
|||||||
GameMain.LightManager.AddRayCastTask(this, drawPos, rotation);
|
GameMain.LightManager.AddRayCastTask(this, drawPos, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float MinPointDistance = 6;
|
||||||
|
|
||||||
public void RayCastTask(Vector2 drawPos, float rotation)
|
public void RayCastTask(Vector2 drawPos, float rotation)
|
||||||
{
|
{
|
||||||
@@ -877,12 +883,11 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const float MinPointDistance = 6;
|
|
||||||
|
|
||||||
//remove points that are very close to each other
|
//remove points that are very close to each other
|
||||||
for (int i = 0; i < points.Count; i++)
|
//+= 2 because the points are added in pairs above, i.e. 0 and 1 belong to the same segment
|
||||||
|
for (int i = 0; i < points.Count; i += 2)
|
||||||
{
|
{
|
||||||
for (int j = Math.Min(i + 4, points.Count - 1); j > i; j--)
|
for (int j = Math.Min(i + 2, points.Count - 1); j > i; j--)
|
||||||
{
|
{
|
||||||
if (Math.Abs(points[i].WorldPos.X - points[j].WorldPos.X) < MinPointDistance &&
|
if (Math.Abs(points[i].WorldPos.X - points[j].WorldPos.X) < MinPointDistance &&
|
||||||
Math.Abs(points[i].WorldPos.Y - points[j].WorldPos.Y) < MinPointDistance)
|
Math.Abs(points[i].WorldPos.Y - points[j].WorldPos.Y) < MinPointDistance)
|
||||||
@@ -892,14 +897,14 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var compareCCW = new CompareSegmentPointCW(drawPos);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
points.Sort(compareCCW);
|
var compareCW = new CompareSegmentPointCW(drawPos);
|
||||||
|
points.Sort(compareCW);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder("Constructing light volumes failed! Light pos: " + drawPos + ", Hull verts:\n");
|
StringBuilder sb = new StringBuilder($"Constructing light volumes failed ({nameof(CompareSegmentPointCW)})! Light pos: {drawPos}, Hull verts:\n");
|
||||||
foreach (SegmentPoint sp in points)
|
foreach (SegmentPoint sp in points)
|
||||||
{
|
{
|
||||||
sb.AppendLine(sp.Pos.ToString());
|
sb.AppendLine(sp.Pos.ToString());
|
||||||
@@ -914,7 +919,11 @@ namespace Barotrauma.Lights
|
|||||||
verts.Clear();
|
verts.Clear();
|
||||||
foreach (SegmentPoint p in points)
|
foreach (SegmentPoint p in points)
|
||||||
{
|
{
|
||||||
Vector2 dir = Vector2.Normalize(p.WorldPos - drawPos);
|
Vector2 diff = p.WorldPos - drawPos;
|
||||||
|
float dist = diff.Length();
|
||||||
|
//light source exactly at the segment point, don't cast a shadow (normalizing the vector would lead to NaN)
|
||||||
|
if (dist <= 0.0001f) { continue; }
|
||||||
|
Vector2 dir = diff / dist;
|
||||||
Vector2 dirNormal = new Vector2(-dir.Y, dir.X) * MinPointDistance;
|
Vector2 dirNormal = new Vector2(-dir.Y, dir.X) * MinPointDistance;
|
||||||
|
|
||||||
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
|
//do two slightly offset raycasts to hit the segment itself and whatever's behind it
|
||||||
@@ -940,9 +949,36 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
//the raycasts landed on different segments
|
//the raycasts landed on different segments
|
||||||
//we definitely want to generate new geometry here
|
//we definitely want to generate new geometry here
|
||||||
verts.Add(isPoint1 ? p.WorldPos : intersection1.pos);
|
if (isPoint1)
|
||||||
verts.Add(isPoint2 ? p.WorldPos : intersection2.pos);
|
{
|
||||||
markAsVisible = true;
|
TryAddPoints(intersection2.pos, p.WorldPos, drawPos, verts);
|
||||||
|
markAsVisible = true;
|
||||||
|
}
|
||||||
|
else if (isPoint2)
|
||||||
|
{
|
||||||
|
TryAddPoints(intersection1.pos, p.WorldPos, drawPos, verts);
|
||||||
|
markAsVisible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//didn't hit either point, completely obstructed
|
||||||
|
verts.Add(intersection1.pos);
|
||||||
|
verts.Add(intersection2.pos);
|
||||||
|
}
|
||||||
|
static void TryAddPoints(Vector2 intersection, Vector2 point, Vector2 refPos, List<Vector2> verts)
|
||||||
|
{
|
||||||
|
//* 0.8f because we don't care about obstacles that are very close (intersecting walls),
|
||||||
|
//only about obstacles that are clearly between the point and the refPos
|
||||||
|
bool intersectionCloserThanPoint = Vector2.DistanceSquared(intersection, refPos) < Vector2.DistanceSquared(point, refPos) * 0.8f;
|
||||||
|
//if the raycast hit a segment that's closer than the point we're aiming towards,
|
||||||
|
//it means we didn't hit a segment behind the point, but something that's obstructing it
|
||||||
|
//= we don't want to add vertex at that obstructed point, it could make the light go through obstacles
|
||||||
|
if (!intersectionCloserThanPoint)
|
||||||
|
{
|
||||||
|
verts.Add(point);
|
||||||
|
}
|
||||||
|
verts.Add(intersection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (markAsVisible)
|
if (markAsVisible)
|
||||||
{
|
{
|
||||||
@@ -959,15 +995,32 @@ namespace Barotrauma.Lights
|
|||||||
//remove points that are very close to each other
|
//remove points that are very close to each other
|
||||||
for (int i = 0; i < verts.Count - 1; i++)
|
for (int i = 0; i < verts.Count - 1; i++)
|
||||||
{
|
{
|
||||||
for (int j = Math.Min(i + 4, verts.Count - 1); j > i; j--)
|
for (int j = verts.Count - 1; j > i; j--)
|
||||||
{
|
{
|
||||||
if (Math.Abs(verts[i].X - verts[j].X) < 6 &&
|
if (Math.Abs(verts[i].X - verts[j].X) < MinPointDistance &&
|
||||||
Math.Abs(verts[i].Y - verts[j].Y) < 6)
|
Math.Abs(verts[i].Y - verts[j].Y) < MinPointDistance)
|
||||||
{
|
{
|
||||||
verts.RemoveAt(j);
|
verts.RemoveAt(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var compareCW = new CompareCW(drawPos);
|
||||||
|
verts.Sort(compareCW);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder($"Constructing light volumes failed ({nameof(CompareSegmentPointCW)})! Light pos: {drawPos}, verts:\n");
|
||||||
|
foreach (Vector2 v in verts)
|
||||||
|
{
|
||||||
|
sb.AppendLine(v.ToString());
|
||||||
|
}
|
||||||
|
DebugConsole.ThrowError(sb.ToString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
calculatedDrawPos = drawPos;
|
calculatedDrawPos = drawPos;
|
||||||
state = LightVertexState.PendingVertexRecalculation;
|
state = LightVertexState.PendingVertexRecalculation;
|
||||||
}
|
}
|
||||||
@@ -1114,7 +1167,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
//add the normals together and use some magic numbers to create
|
//add the normals together and use some magic numbers to create
|
||||||
//a somewhat useful/good-looking blur
|
//a somewhat useful/good-looking blur
|
||||||
float blurDistance = 40.0f;
|
float blurDistance = 25.0f;
|
||||||
Vector2 nDiff = nDiff1 * blurDistance;
|
Vector2 nDiff = nDiff1 * blurDistance;
|
||||||
if (MathUtils.GetLineIntersection(vertex + (nDiff1 * blurDistance), nextVertex + (nDiff1 * blurDistance), vertex + (nDiff2 * blurDistance), prevVertex + (nDiff2 * blurDistance), true, out Vector2 intersection))
|
if (MathUtils.GetLineIntersection(vertex + (nDiff1 * blurDistance), nextVertex + (nDiff1 * blurDistance), vertex + (nDiff2 * blurDistance), prevVertex + (nDiff2 * blurDistance), true, out Vector2 intersection))
|
||||||
{
|
{
|
||||||
@@ -1230,7 +1283,8 @@ namespace Barotrauma.Lights
|
|||||||
/// <param name="spriteBatch"></param>
|
/// <param name="spriteBatch"></param>
|
||||||
public void DrawSprite(SpriteBatch spriteBatch, Camera cam)
|
public void DrawSprite(SpriteBatch spriteBatch, Camera cam)
|
||||||
{
|
{
|
||||||
if (GameMain.DebugDraw)
|
//uncomment if you want to visualize the bounds of the light volume
|
||||||
|
/*if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
Vector2 drawPos = position;
|
Vector2 drawPos = position;
|
||||||
if (ParentSub != null)
|
if (ParentSub != null)
|
||||||
@@ -1269,7 +1323,7 @@ namespace Barotrauma.Lights
|
|||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch, boundaryCorners[i].Pos, boundaryCorners[(i + 1) % 4].Pos, Color.White, 0, 3);
|
GUI.DrawLine(spriteBatch, boundaryCorners[i].Pos, boundaryCorners[(i + 1) % 4].Pos, Color.White, 0, 3);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (DeformableLightSprite != null)
|
if (DeformableLightSprite != null)
|
||||||
{
|
{
|
||||||
@@ -1318,7 +1372,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
if (LightTextureTargetSize != Vector2.Zero)
|
if (LightTextureTargetSize != Vector2.Zero)
|
||||||
{
|
{
|
||||||
LightSprite.DrawTiled(spriteBatch, drawPos, LightTextureTargetSize, color, startOffset: LightTextureOffset, textureScale: LightTextureScale);
|
LightSprite.DrawTiled(spriteBatch, drawPos, LightTextureTargetSize, color: color, startOffset: LightTextureOffset, textureScale: LightTextureScale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1367,6 +1421,38 @@ namespace Barotrauma.Lights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DebugDrawVertices(SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }
|
||||||
|
|
||||||
|
//commented out because this is mostly just useful in very specific situations, otherwise it just makes debugdraw very messy
|
||||||
|
//(you may also need to add a condition here that only draws this for the specific light you're interested in)
|
||||||
|
if (GameMain.DebugDraw && vertices != null)
|
||||||
|
{
|
||||||
|
if (ParentBody?.UserData is Item it && it.Prefab.Identifier == "flashlight")
|
||||||
|
|
||||||
|
for (int i = 1; i < vertices.Length - 1; i += 2)
|
||||||
|
{
|
||||||
|
Vector2 vert1 = new Vector2(vertices[i].Position.X, vertices[i].Position.Y);
|
||||||
|
int nextIndex = (i + 2) % vertices.Length;
|
||||||
|
//the first vertex is the one at the position of the light source, skip that one
|
||||||
|
//(we just want to draw lines between the vertices at the circumference of the light volume)
|
||||||
|
if (nextIndex == 0) { nextIndex++; }
|
||||||
|
Vector2 vert2 = new Vector2(vertices[nextIndex].Position.X, vertices[nextIndex].Position.Y);
|
||||||
|
if (ParentSub != null)
|
||||||
|
{
|
||||||
|
vert1 += ParentSub.DrawPosition;
|
||||||
|
vert2 += ParentSub.DrawPosition;
|
||||||
|
}
|
||||||
|
vert1.Y = -vert1.Y;
|
||||||
|
vert2.Y = -vert2.Y;
|
||||||
|
|
||||||
|
var randomColor = ToolBox.GradientLerp(i / (float)vertices.Length, Color.Magenta, Color.Blue, Color.Yellow, Color.Green, Color.Cyan, Color.Red, Color.Purple, Color.Yellow);
|
||||||
|
GUI.DrawLine(spriteBatch, vert1, vert2, randomColor * 0.8f, width: 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform, bool allowRecalculation, ref int recalculationCount)
|
public void DrawLightVolume(SpriteBatch spriteBatch, BasicEffect lightEffect, Matrix transform, bool allowRecalculation, ref int recalculationCount)
|
||||||
{
|
{
|
||||||
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }
|
if (Range < 1.0f || Color.A < 1 || CurrentBrightness <= 0.0f) { return; }
|
||||||
|
|||||||
@@ -291,14 +291,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly List<MapNotification> mapNotifications = new List<MapNotification>();
|
private readonly List<MapNotification> mapNotifications = new List<MapNotification>();
|
||||||
|
|
||||||
partial void ChangeLocationTypeProjSpecific(Location location, string prevName, LocationTypeChange change)
|
partial void ChangeLocationTypeProjSpecific(Location location, LocalizedString prevName, LocationTypeChange change)
|
||||||
{
|
{
|
||||||
var messages = change.GetMessages(location.Faction);
|
var messages = change.GetMessages(location.Faction);
|
||||||
if (!messages.Any()) { return; }
|
if (!messages.Any()) { return; }
|
||||||
|
|
||||||
string msg = messages.GetRandom(Rand.RandSync.Unsynced)
|
string msg = messages.GetRandom(Rand.RandSync.Unsynced)
|
||||||
.Replace("[previousname]", $"‖color:gui.yellow‖{prevName}‖end‖")
|
.Replace("[previousname]", $"‖color:gui.yellow‖{prevName}‖end‖")
|
||||||
.Replace("[name]", $"‖color:gui.yellow‖{location.Name}‖end‖");
|
.Replace("[name]", $"‖color:gui.yellow‖{location.DisplayName}‖end‖");
|
||||||
location.LastTypeChangeMessage = msg;
|
location.LastTypeChangeMessage = msg;
|
||||||
|
|
||||||
mapNotifications.Add(new MapNotification(msg, GUIStyle.SubHeadingFont, mapNotifications, location));
|
mapNotifications.Add(new MapNotification(msg, GUIStyle.SubHeadingFont, mapNotifications, location));
|
||||||
@@ -377,7 +377,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool showReputation = hudVisibility > 0.0f && location.Type.HasOutpost && location.Reputation != null;
|
bool showReputation = hudVisibility > 0.0f && location.Type.HasOutpost && location.Reputation != null;
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Name, font: GUIStyle.LargeFont) { Padding = Vector4.Zero };
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.DisplayName, font: GUIStyle.LargeFont) { Padding = Vector4.Zero };
|
||||||
if (!location.Type.Name.IsNullOrEmpty())
|
if (!location.Type.Name.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
||||||
@@ -1080,6 +1080,7 @@ 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;
|
||||||
|
if (connectionSprite?.Texture == null) { continue; }
|
||||||
|
|
||||||
Color segmentColor = connectionColor;
|
Color segmentColor = connectionColor;
|
||||||
int segmentWidth = width;
|
int segmentWidth = width;
|
||||||
@@ -1092,9 +1093,6 @@ namespace Barotrauma
|
|||||||
segmentWidth /= 2;
|
segmentWidth /= 2;
|
||||||
segmentColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
|
segmentColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Draw(connectionSprite.Texture,
|
spriteBatch.Draw(connectionSprite.Texture,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Vector2 spriteScale = new Vector2(zoom);
|
Vector2 spriteScale = new Vector2(zoom);
|
||||||
|
|
||||||
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, Params.RadiationAreaColor, Vector2.Zero, textureScale: spriteScale);
|
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, color: Params.RadiationAreaColor, startOffset: Vector2.Zero, textureScale: spriteScale);
|
||||||
|
|
||||||
Vector2 topRight = topLeft + Vector2.UnitX * size.X;
|
Vector2 topRight = topLeft + Vector2.UnitX * size.X;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Lights;
|
using Barotrauma.Lights;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -65,9 +66,7 @@ namespace Barotrauma
|
|||||||
disableSelect = value;
|
disableSelect = value;
|
||||||
if (disableSelect)
|
if (disableSelect)
|
||||||
{
|
{
|
||||||
startMovingPos = Vector2.Zero;
|
StopSelection();
|
||||||
selectionSize = Vector2.Zero;
|
|
||||||
selectionPos = Vector2.Zero;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,21 +162,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (SelectedAny)
|
if (SelectedAny)
|
||||||
{
|
{
|
||||||
if (SelectedList.Any(static t => t is Item it && it.GetComponent<CircuitBox>() is not null))
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(SelectedList), true));
|
||||||
{
|
SelectedList.ForEachMod(static e => { if (!e.Removed) { e.Remove(); } });
|
||||||
GUI.AskForConfirmation(SubEditorScreen.CircuitBoxDeletionWarningHeader, SubEditorScreen.CircuitBoxDeletionWarningBody, onConfirm: Delete);
|
SelectedList.Clear();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delete()
|
|
||||||
{
|
|
||||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(SelectedList), true));
|
|
||||||
SelectedList.ForEach(static e => { if (!e.Removed) { e.Remove(); } });
|
|
||||||
SelectedList.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,6 +481,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void StopSelection()
|
||||||
|
{
|
||||||
|
startMovingPos = Vector2.Zero;
|
||||||
|
selectionSize = Vector2.Zero;
|
||||||
|
selectionPos = Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector2 GetNudgeAmount(bool doHold = true)
|
public static Vector2 GetNudgeAmount(bool doHold = true)
|
||||||
{
|
{
|
||||||
Vector2 nudgeAmount = Vector2.Zero;
|
Vector2 nudgeAmount = Vector2.Zero;
|
||||||
@@ -792,12 +786,16 @@ namespace Barotrauma
|
|||||||
foreach (MapEntity e in SelectedList)
|
foreach (MapEntity e in SelectedList)
|
||||||
{
|
{
|
||||||
SpriteEffects spriteEffects = SpriteEffects.None;
|
SpriteEffects spriteEffects = SpriteEffects.None;
|
||||||
|
float spriteRotation = 0.0f;
|
||||||
|
float rectangleRotation = 0.0f;
|
||||||
switch (e)
|
switch (e)
|
||||||
{
|
{
|
||||||
case Item item:
|
case Item item:
|
||||||
{
|
{
|
||||||
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
||||||
if (item.flippedY && item.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
if (item.FlippedY && item.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
||||||
|
spriteRotation = MathHelper.ToRadians(item.Rotation);
|
||||||
|
rectangleRotation = spriteRotation;
|
||||||
var wire = item.GetComponent<Wire>();
|
var wire = item.GetComponent<Wire>();
|
||||||
if (wire != null && wire.Item.body != null && !wire.Item.body.Enabled)
|
if (wire != null && wire.Item.body != null && !wire.Item.body.Enabled)
|
||||||
{
|
{
|
||||||
@@ -809,7 +807,10 @@ namespace Barotrauma
|
|||||||
case Structure structure:
|
case Structure structure:
|
||||||
{
|
{
|
||||||
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
||||||
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
if (structure.FlippedY && structure.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
||||||
|
spriteRotation = MathHelper.ToRadians(structure.Rotation);
|
||||||
|
rectangleRotation = spriteRotation;
|
||||||
|
if (structure.FlippedX != structure.FlippedY) { rectangleRotation = -rectangleRotation; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WayPoint wayPoint:
|
case WayPoint wayPoint:
|
||||||
@@ -831,11 +832,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.Prefab?.DrawPlacing(spriteBatch,
|
e.Prefab?.DrawPlacing(spriteBatch,
|
||||||
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteEffects);
|
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteRotation, spriteEffects: spriteEffects);
|
||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
new Vector2(e.WorldRect.X, -e.WorldRect.Y) + moveAmount,
|
center: e.WorldRect.Center.ToVector2().FlipY() + moveAmount + new Vector2(0f, e.WorldRect.Height),
|
||||||
new Vector2(e.rect.Width, e.rect.Height),
|
width: e.WorldRect.Width, height: e.WorldRect.Height,
|
||||||
Color.White, false, 0, (int)Math.Max(3.0f / GameScreen.Selected.Cam.Zoom, 2.0f));
|
rotation: rectangleRotation, clr: Color.White,
|
||||||
|
depth: 0f, thickness: Math.Max(3.0f / GameScreen.Selected.Cam.Zoom, 2.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
//stop dragging the "selection rectangle"
|
//stop dragging the "selection rectangle"
|
||||||
@@ -877,6 +879,23 @@ namespace Barotrauma
|
|||||||
spriteBatch.DrawLine(corners[3] + offset, corners[0] - offset, color, thickness);
|
spriteBatch.DrawLine(corners[3] + offset, corners[0] - offset, color, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void ColorFlipButton(GUIButton btn, bool flip)
|
||||||
|
{
|
||||||
|
var color = flip ? GUIStyle.Green : Color.White;
|
||||||
|
var hsv = ToolBox.RGBToHSV(color);
|
||||||
|
|
||||||
|
// Boost saturation and reduce value a bit because our default colors are too muted for this button's style
|
||||||
|
var hsvBase = hsv;
|
||||||
|
hsvBase.Y *= 4f;
|
||||||
|
hsvBase.Z *= 0.8f;
|
||||||
|
btn.Color = ToolBox.HSVToRGB(hsvBase.X, hsvBase.Y, hsvBase.Z);
|
||||||
|
btn.SelectedColor = ToolBox.HSVToRGB(hsvBase.X, hsvBase.Y, hsvBase.Z);
|
||||||
|
|
||||||
|
var hsvHover = hsv;
|
||||||
|
hsvHover.Z *= 1.2f;
|
||||||
|
btn.HoverColor = ToolBox.HSVToRGB(hsvHover.X, hsvHover.Y, hsvHover.Z);
|
||||||
|
}
|
||||||
|
|
||||||
public static List<MapEntity> FilteredSelectedList { get; private set; } = new List<MapEntity>();
|
public static List<MapEntity> FilteredSelectedList { get; private set; } = new List<MapEntity>();
|
||||||
|
|
||||||
public static void UpdateEditor(Camera cam, float deltaTime)
|
public static void UpdateEditor(Camera cam, float deltaTime)
|
||||||
@@ -1105,6 +1124,25 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public virtual void DrawEditing(SpriteBatch spriteBatch, Camera cam) { }
|
public virtual void DrawEditing(SpriteBatch spriteBatch, Camera cam) { }
|
||||||
|
|
||||||
|
private float RotationRad
|
||||||
|
=> MathHelper.ToRadians(
|
||||||
|
this switch
|
||||||
|
{
|
||||||
|
Structure s => s.Rotation,
|
||||||
|
Item it => it.Rotation,
|
||||||
|
_ => 0.0f
|
||||||
|
});
|
||||||
|
|
||||||
|
private Vector2 GetEditingHandlePos(int x, int y, Camera cam)
|
||||||
|
{
|
||||||
|
Vector2 handleDiff = new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f));
|
||||||
|
var rotation = -RotationRad;
|
||||||
|
handleDiff = MathUtils.RotatePoint(handleDiff, rotation);
|
||||||
|
if (FlippedX) { handleDiff = handleDiff.FlipX(); }
|
||||||
|
if (FlippedY) { handleDiff = handleDiff.FlipY(); }
|
||||||
|
return cam.WorldToScreen(Position + handleDiff);
|
||||||
|
}
|
||||||
|
|
||||||
float ResizeHandleSize => 10 * GUI.Scale;
|
float ResizeHandleSize => 10 * GUI.Scale;
|
||||||
float ResizeHandleHighlightDistance => 8 * GUI.Scale;
|
float ResizeHandleHighlightDistance => 8 * GUI.Scale;
|
||||||
|
|
||||||
@@ -1119,9 +1157,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
for (int y = startY; y < 2; y += 2)
|
for (int y = startY; y < 2; y += 2)
|
||||||
{
|
{
|
||||||
Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f)));
|
Vector2 handlePos = GetEditingHandlePos(x, y, cam);
|
||||||
|
|
||||||
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
|
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
|
||||||
|
|
||||||
if (highlighted && PlayerInput.PrimaryMouseButtonDown())
|
if (highlighted && PlayerInput.PrimaryMouseButtonDown())
|
||||||
{
|
{
|
||||||
selectionPos = Vector2.Zero;
|
selectionPos = Vector2.Zero;
|
||||||
@@ -1138,44 +1177,83 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (prevRect == null)
|
if (prevRect == null)
|
||||||
{
|
{
|
||||||
prevRect = new Rectangle(Rect.Location, Rect.Size);
|
prevRect = Rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 placePosition = new Vector2(rect.X, rect.Y);
|
Vector2 placePosition = prevRect.Value.Location.ToVector2();
|
||||||
Vector2 placeSize = new Vector2(rect.Width, rect.Height);
|
Vector2 placeSize = prevRect.Value.Size.ToVector2();
|
||||||
|
|
||||||
Vector2 mousePos = Submarine.MouseToWorldGrid(cam, Submarine.MainSub, round: true);
|
static Vector2 flipThenRotate(Vector2 point, Vector2 center, float angle, bool flipX, bool flipY)
|
||||||
|
|
||||||
if (PlayerInput.IsShiftDown())
|
|
||||||
{
|
{
|
||||||
mousePos = cam.ScreenToWorld(PlayerInput.MousePosition);
|
if (flipX) { point = (point - center).FlipX() + center; }
|
||||||
|
if (flipY) { point = (point - center).FlipY() + center; }
|
||||||
|
|
||||||
|
point = MathUtils.RotatePointAroundTarget(point, center, angle);
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector2 rotateThenFlip(Vector2 point, Vector2 center, float angle, bool flipX, bool flipY)
|
||||||
|
{
|
||||||
|
point = MathUtils.RotatePointAroundTarget(point, center, angle);
|
||||||
|
|
||||||
|
if (flipX) { point = (point - center).FlipX() + center; }
|
||||||
|
if (flipY) { point = (point - center).FlipY() + center; }
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 mousePos = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
Vector2 prevPos = placePosition;
|
||||||
|
Vector2 prevOppositeCorner = prevPos + placeSize.FlipY();
|
||||||
|
Vector2 prevCenter = placePosition + placeSize.FlipY() * 0.5f;
|
||||||
|
mousePos = flipThenRotate(mousePos, prevCenter, RotationRad, FlippedX, FlippedY);
|
||||||
|
|
||||||
|
if (!PlayerInput.IsShiftDown())
|
||||||
|
{
|
||||||
|
mousePos = Submarine.VectorToWorldGrid(mousePos, Submarine.MainSub, round: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resizeDirX > 0)
|
if (resizeDirX > 0)
|
||||||
{
|
{
|
||||||
mousePos.X = Math.Max(mousePos.X, rect.X + Submarine.GridSize.X);
|
mousePos.X = Math.Max(mousePos.X, prevRect.Value.X + Submarine.GridSize.X);
|
||||||
placeSize.X = mousePos.X - placePosition.X;
|
placeSize.X = mousePos.X - placePosition.X;
|
||||||
}
|
}
|
||||||
else if (resizeDirX < 0)
|
else if (resizeDirX < 0)
|
||||||
{
|
{
|
||||||
mousePos.X = Math.Min(mousePos.X, rect.Right - Submarine.GridSize.X);
|
mousePos.X = Math.Min(mousePos.X, prevRect.Value.Right - Submarine.GridSize.X);
|
||||||
|
|
||||||
placeSize.X = MathF.Round((placePosition.X + placeSize.X) - mousePos.X);
|
placeSize.X = MathF.Round((placePosition.X + placeSize.X) - mousePos.X);
|
||||||
placePosition.X = MathF.Round(mousePos.X);
|
placePosition.X = MathF.Round(mousePos.X);
|
||||||
}
|
}
|
||||||
if (resizeDirY < 0)
|
if (resizeDirY < 0)
|
||||||
{
|
{
|
||||||
mousePos.Y = Math.Min(mousePos.Y, rect.Y - Submarine.GridSize.Y);
|
mousePos.Y = Math.Min(mousePos.Y, prevRect.Value.Y - Submarine.GridSize.Y);
|
||||||
placeSize.Y = placePosition.Y - mousePos.Y;
|
placeSize.Y = placePosition.Y - mousePos.Y;
|
||||||
}
|
}
|
||||||
else if (resizeDirY > 0)
|
else if (resizeDirY > 0)
|
||||||
{
|
{
|
||||||
mousePos.Y = Math.Max(mousePos.Y, rect.Y - rect.Height + Submarine.GridSize.X);
|
mousePos.Y = Math.Max(mousePos.Y, prevRect.Value.Y - prevRect.Value.Height + Submarine.GridSize.Y);
|
||||||
|
|
||||||
placeSize.Y = mousePos.Y - (rect.Y - rect.Height);
|
placeSize.Y = mousePos.Y - (prevRect.Value.Y - prevRect.Value.Height);
|
||||||
placePosition.Y = mousePos.Y;
|
placePosition.Y = mousePos.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 newPos = placePosition;
|
||||||
|
Vector2 newOppositeCorner = placePosition + placeSize.FlipY();
|
||||||
|
|
||||||
|
Vector2 transformedCornerDiff = rotateThenFlip(newPos-prevPos, Vector2.Zero, -RotationRad, FlippedX, FlippedY);
|
||||||
|
Vector2 transformedOppositeCornerDiff = rotateThenFlip(newOppositeCorner-prevOppositeCorner, Vector2.Zero, -RotationRad, FlippedX, FlippedY);
|
||||||
|
|
||||||
|
Vector2 newPosTransformed = rotateThenFlip(prevPos, prevCenter, -RotationRad, FlippedX, FlippedY)
|
||||||
|
+ transformedCornerDiff;
|
||||||
|
Vector2 newOppositeTransformed = rotateThenFlip(prevOppositeCorner, prevCenter, -RotationRad, FlippedX, FlippedY)
|
||||||
|
+ transformedOppositeCornerDiff;
|
||||||
|
Vector2 newTransformedCenter = (newPosTransformed + newOppositeTransformed) * 0.5f;
|
||||||
|
|
||||||
|
var newDiff = (newOppositeCorner - newPos) * 0.5f;
|
||||||
|
placePosition = newTransformedCenter - newDiff;
|
||||||
|
|
||||||
if ((int)placePosition.X != rect.X || (int)placePosition.Y != rect.Y || (int)placeSize.X != rect.Width || (int)placeSize.Y != rect.Height)
|
if ((int)placePosition.X != rect.X || (int)placePosition.Y != rect.Y || (int)placeSize.X != rect.Width || (int)placeSize.Y != rect.Height)
|
||||||
{
|
{
|
||||||
Rect = new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y);
|
Rect = new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y);
|
||||||
@@ -1210,15 +1288,16 @@ namespace Barotrauma
|
|||||||
IsHighlighted = true;
|
IsHighlighted = true;
|
||||||
|
|
||||||
int startX = ResizeHorizontal ? -1 : 0;
|
int startX = ResizeHorizontal ? -1 : 0;
|
||||||
int StartY = ResizeVertical ? -1 : 0;
|
int startY = ResizeVertical ? -1 : 0;
|
||||||
|
|
||||||
for (int x = startX; x < 2; x += 2)
|
for (int x = startX; x < 2; x += 2)
|
||||||
{
|
{
|
||||||
for (int y = StartY; y < 2; y += 2)
|
for (int y = startY; y < 2; y += 2)
|
||||||
{
|
{
|
||||||
Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f)));
|
Vector2 handlePos = GetEditingHandlePos(x, y, cam);
|
||||||
|
|
||||||
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
|
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
|
||||||
|
var color = Color.White * (highlighted ? 1.0f : 0.6f);
|
||||||
if (highlighted && !PlayerInput.PrimaryMouseButtonHeld())
|
if (highlighted && !PlayerInput.PrimaryMouseButtonHeld())
|
||||||
{
|
{
|
||||||
GUI.MouseCursor = CursorState.Hand;
|
GUI.MouseCursor = CursorState.Hand;
|
||||||
@@ -1226,7 +1305,7 @@ namespace Barotrauma
|
|||||||
GUI.DrawRectangle(spriteBatch,
|
GUI.DrawRectangle(spriteBatch,
|
||||||
handlePos - new Vector2(ResizeHandleSize / 2),
|
handlePos - new Vector2(ResizeHandleSize / 2),
|
||||||
new Vector2(ResizeHandleSize),
|
new Vector2(ResizeHandleSize),
|
||||||
Color.White * (highlighted ? 1.0f : 0.6f),
|
color,
|
||||||
true, 0,
|
true, 0,
|
||||||
(int)Math.Max(1.5f / GameScreen.Selected.Cam.Zoom, 1.0f));
|
(int)Math.Max(1.5f / GameScreen.Selected.Cam.Zoom, 1.0f));
|
||||||
}
|
}
|
||||||
@@ -1241,12 +1320,15 @@ namespace Barotrauma
|
|||||||
HashSet<MapEntity> foundEntities = new HashSet<MapEntity>();
|
HashSet<MapEntity> foundEntities = new HashSet<MapEntity>();
|
||||||
|
|
||||||
Rectangle selectionRect = Submarine.AbsRect(pos, size);
|
Rectangle selectionRect = Submarine.AbsRect(pos, size);
|
||||||
|
Quad2D selectionQuad = Quad2D.FromSubmarineRectangle(selectionRect);
|
||||||
|
|
||||||
foreach (MapEntity entity in MapEntityList)
|
foreach (MapEntity entity in MapEntityList)
|
||||||
{
|
{
|
||||||
if (!entity.SelectableInEditor) { continue; }
|
if (!entity.SelectableInEditor) { continue; }
|
||||||
|
|
||||||
if (Submarine.RectsOverlap(selectionRect, entity.rect))
|
Quad2D entityQuad = entity.GetTransformedQuad();
|
||||||
|
|
||||||
|
if (selectionQuad.Intersects(entityQuad))
|
||||||
{
|
{
|
||||||
foundEntities.Add(entity);
|
foundEntities.Add(entity);
|
||||||
entity.IsIncludedInSelection = true;
|
entity.IsIncludedInSelection = true;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DrawPlacing(SpriteBatch spriteBatch, Rectangle drawRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
public virtual void DrawPlacing(SpriteBatch spriteBatch, Rectangle drawRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||||
{
|
{
|
||||||
if (Submarine.MainSub != null)
|
if (Submarine.MainSub != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using Barotrauma.Sounds;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Xml.Linq;
|
|
||||||
using Barotrauma.Sounds;
|
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -45,7 +44,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (FrequencyMultiplierRange.Y > 4.0f)
|
if (FrequencyMultiplierRange.Y > 4.0f)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")");
|
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")",
|
||||||
|
contentPackage: element.ContentPackage);
|
||||||
}
|
}
|
||||||
IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
|
IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,8 @@ namespace Barotrauma
|
|||||||
if (filename is null)
|
if (filename is null)
|
||||||
{
|
{
|
||||||
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
||||||
DebugConsole.ThrowError(errorMsg);
|
DebugConsole.ThrowError(errorMsg,
|
||||||
|
contentPackage: element.ContentPackage);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,8 @@ namespace Barotrauma
|
|||||||
catch (System.IO.FileNotFoundException e)
|
catch (System.IO.FileNotFoundException e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to load sound file \"" + filename + "\" (file not found).";
|
string errorMsg = "Failed to load sound file \"" + filename + "\" (file not found).";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e,
|
||||||
|
contentPackage: element.ContentPackage);
|
||||||
if (!ContentPackageManager.ModsEnabled)
|
if (!ContentPackageManager.ModsEnabled)
|
||||||
{
|
{
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
@@ -96,7 +98,8 @@ namespace Barotrauma
|
|||||||
catch (System.IO.InvalidDataException e)
|
catch (System.IO.InvalidDataException e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to load sound file \"" + filename + "\" (invalid data).";
|
string errorMsg = "Failed to load sound file \"" + filename + "\" (invalid data).";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e,
|
||||||
|
contentPackage: element.ContentPackage);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:InvalidData" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:InvalidData" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -123,7 +126,8 @@ namespace Barotrauma
|
|||||||
catch (System.IO.FileNotFoundException e)
|
catch (System.IO.FileNotFoundException e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
|
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
|
||||||
DebugConsole.ThrowError(errorMsg, e);
|
DebugConsole.ThrowError(errorMsg, e,
|
||||||
|
contentPackage: roundSound.Sound?.XElement?.ContentPackage);
|
||||||
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ namespace Barotrauma
|
|||||||
Stretch = true,
|
Stretch = true,
|
||||||
RelativeSpacing = 0.01f
|
RelativeSpacing = 0.01f
|
||||||
};
|
};
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
|
||||||
|
var mirrorX = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
@@ -160,10 +161,12 @@ namespace Barotrauma
|
|||||||
me.FlipX(relativeToSub: false);
|
me.FlipX(relativeToSub: false);
|
||||||
}
|
}
|
||||||
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
|
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
|
||||||
|
ColorFlipButton(button, FlippedX);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
ColorFlipButton(mirrorX, FlippedX);
|
||||||
|
var mirrorY = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
@@ -173,9 +176,11 @@ namespace Barotrauma
|
|||||||
me.FlipY(relativeToSub: false);
|
me.FlipY(relativeToSub: false);
|
||||||
}
|
}
|
||||||
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
|
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
|
||||||
|
ColorFlipButton(button, FlippedY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
ColorFlipButton(mirrorY, FlippedY);
|
||||||
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall")
|
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall")
|
||||||
{
|
{
|
||||||
OnClicked = (button, data) =>
|
OnClicked = (button, data) =>
|
||||||
@@ -231,11 +236,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override bool IsVisible(Rectangle worldView)
|
public override bool IsVisible(Rectangle worldView)
|
||||||
{
|
{
|
||||||
Rectangle worldRect = WorldRect;
|
RectangleF worldRect = Quad2D.FromSubmarineRectangle(WorldRect).Rotated(
|
||||||
|
FlippedX != FlippedY
|
||||||
|
? rotationRad
|
||||||
|
: -rotationRad).BoundingAxisAlignedRectangle;
|
||||||
Vector2 worldPos = WorldPosition;
|
Vector2 worldPos = WorldPosition;
|
||||||
|
|
||||||
Vector2 min = new Vector2(worldRect.X, worldRect.Y - worldRect.Height);
|
Vector2 min = new Vector2(worldRect.X, worldRect.Y);
|
||||||
Vector2 max = new Vector2(worldRect.Right, worldRect.Y);
|
Vector2 max = new Vector2(worldRect.Right, worldRect.Y + worldRect.Height);
|
||||||
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
|
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
float scale = decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale;
|
float scale = decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale;
|
||||||
@@ -307,7 +315,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Vector2 bodyPos = WorldPosition + BodyOffset * Scale;
|
Vector2 bodyPos = WorldPosition + BodyOffset * Scale;
|
||||||
|
|
||||||
GUI.DrawRectangle(spriteBatch, new Vector2(bodyPos.X, -bodyPos.Y), rectSize.X, rectSize.Y, BodyRotation, Color.White,
|
GUI.DrawRectangle(sb: spriteBatch,
|
||||||
|
center: new Vector2(bodyPos.X, -bodyPos.Y),
|
||||||
|
width: rectSize.X,
|
||||||
|
height: rectSize.Y,
|
||||||
|
rotation: BodyRotation,
|
||||||
|
clr: Color.White,
|
||||||
thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
|
thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,8 +370,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Prefab.BackgroundSprite.DrawTiled(
|
Prefab.BackgroundSprite.DrawTiled(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
|
new Vector2(rect.X + rect.Width / 2 + drawOffset.X, -(rect.Y - rect.Height / 2 + drawOffset.Y)),
|
||||||
new Vector2(rect.Width, rect.Height),
|
new Vector2(rect.Width, rect.Height),
|
||||||
|
rotation: rotationRad,
|
||||||
|
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
|
||||||
color: Prefab.BackgroundSpriteColor,
|
color: Prefab.BackgroundSpriteColor,
|
||||||
textureScale: TextureScale * Scale,
|
textureScale: TextureScale * Scale,
|
||||||
startOffset: backGroundOffset,
|
startOffset: backGroundOffset,
|
||||||
@@ -368,8 +383,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Prefab.BackgroundSprite.DrawTiled(
|
Prefab.BackgroundSprite.DrawTiled(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset,
|
new Vector2(rect.X + rect.Width / 2 + drawOffset.X, -(rect.Y - rect.Height / 2 + drawOffset.Y)) + dropShadowOffset,
|
||||||
new Vector2(rect.Width, rect.Height),
|
new Vector2(rect.Width, rect.Height),
|
||||||
|
rotation: rotationRad,
|
||||||
|
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
|
||||||
color: Color.Black * 0.5f,
|
color: Color.Black * 0.5f,
|
||||||
textureScale: TextureScale * Scale,
|
textureScale: TextureScale * Scale,
|
||||||
startOffset: backGroundOffset,
|
startOffset: backGroundOffset,
|
||||||
@@ -385,6 +402,13 @@ namespace Barotrauma
|
|||||||
SpriteEffects oldEffects = Prefab.Sprite.effects;
|
SpriteEffects oldEffects = Prefab.Sprite.effects;
|
||||||
Prefab.Sprite.effects ^= SpriteEffects;
|
Prefab.Sprite.effects ^= SpriteEffects;
|
||||||
|
|
||||||
|
Vector2 advanceX = MathUtils.RotatedUnitXRadians(this.rotationRad).FlipY();
|
||||||
|
Vector2 advanceY = advanceX.YX().FlipX();
|
||||||
|
if (FlippedX != FlippedY)
|
||||||
|
{
|
||||||
|
advanceX = advanceX.FlipY();
|
||||||
|
advanceY = advanceY.FlipX();
|
||||||
|
}
|
||||||
for (int i = 0; i < Sections.Length; i++)
|
for (int i = 0; i < Sections.Length; i++)
|
||||||
{
|
{
|
||||||
Rectangle drawSection = Sections[i].rect;
|
Rectangle drawSection = Sections[i].rect;
|
||||||
@@ -409,7 +433,7 @@ namespace Barotrauma
|
|||||||
drawSection = new Rectangle(
|
drawSection = new Rectangle(
|
||||||
drawSection.X,
|
drawSection.X,
|
||||||
drawSection.Y,
|
drawSection.Y,
|
||||||
Sections[Sections.Length -1 ].rect.Right - drawSection.X,
|
Sections[Sections.Length - 1].rect.Right - drawSection.X,
|
||||||
drawSection.Y - (Sections[Sections.Length - 1].rect.Y - Sections[Sections.Length - 1].rect.Height));
|
drawSection.Y - (Sections[Sections.Length - 1].rect.Y - Sections[Sections.Length - 1].rect.Height));
|
||||||
i = Sections.Length;
|
i = Sections.Length;
|
||||||
}
|
}
|
||||||
@@ -424,10 +448,18 @@ namespace Barotrauma
|
|||||||
sectionOffset.X += MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.Sprite.SourceRect.Width);
|
sectionOffset.X += MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.Sprite.SourceRect.Width);
|
||||||
sectionOffset.Y += MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.Sprite.SourceRect.Height);
|
sectionOffset.Y += MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.Sprite.SourceRect.Height);
|
||||||
|
|
||||||
|
Vector2 pos = new Vector2(drawSection.X, drawSection.Y);
|
||||||
|
pos -= rect.Location.ToVector2();
|
||||||
|
pos = advanceX * pos.X + advanceY * pos.Y;
|
||||||
|
pos += rect.Location.ToVector2();
|
||||||
|
pos = new Vector2(pos.X + rect.Width / 2 + drawOffset.X, -(pos.Y - rect.Height / 2 + drawOffset.Y));
|
||||||
|
|
||||||
Prefab.Sprite.DrawTiled(
|
Prefab.Sprite.DrawTiled(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(drawSection.X + drawOffset.X, -(drawSection.Y + drawOffset.Y)),
|
pos,
|
||||||
new Vector2(drawSection.Width, drawSection.Height),
|
new Vector2(drawSection.Width, drawSection.Height),
|
||||||
|
rotation: rotationRad,
|
||||||
|
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
|
||||||
color: color,
|
color: color,
|
||||||
startOffset: sectionOffset,
|
startOffset: sectionOffset,
|
||||||
depth: depth,
|
depth: depth,
|
||||||
@@ -437,7 +469,7 @@ namespace Barotrauma
|
|||||||
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
foreach (var decorativeSprite in Prefab.DecorativeSprites)
|
||||||
{
|
{
|
||||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
|
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor) + this.rotationRad;
|
||||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier) * Scale;
|
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier) * Scale;
|
||||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
|
||||||
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, Prefab.Sprite.effects,
|
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, Prefab.Sprite.effects,
|
||||||
|
|||||||
@@ -94,19 +94,20 @@ namespace Barotrauma
|
|||||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White);
|
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||||
{
|
{
|
||||||
SpriteEffects oldEffects = Sprite.effects;
|
var position = placeRect.Location.ToVector2().FlipY();
|
||||||
Sprite.effects ^= spriteEffects;
|
position += placeRect.Size.ToVector2() * 0.5f;
|
||||||
|
|
||||||
Sprite.DrawTiled(
|
Sprite.DrawTiled(
|
||||||
spriteBatch,
|
spriteBatch,
|
||||||
new Vector2(placeRect.X, -placeRect.Y),
|
position,
|
||||||
new Vector2(placeRect.Width, placeRect.Height),
|
placeRect.Size.ToVector2(),
|
||||||
color: Color.White * 0.8f,
|
color: Color.White * 0.8f,
|
||||||
textureScale: TextureScale * scale);
|
origin: placeRect.Size.ToVector2() * 0.5f,
|
||||||
|
rotation: rotation,
|
||||||
Sprite.effects = oldEffects;
|
textureScale: TextureScale * scale,
|
||||||
|
spriteEffects: spriteEffects ^ Sprite.effects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Margin applied around the view area when culling entities (i.e. entities that are this far outside the view are still considered visible)
|
/// Margin applied around the view area when culling entities (i.e. entities that are this far outside the view are still considered visible)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const int CullMargin = 500;
|
private const int CullMargin = 50;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update entity culling when any corner of the view has moved more than this
|
/// Update entity culling when any corner of the view has moved more than this
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -713,18 +713,12 @@ namespace Barotrauma
|
|||||||
return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
|
return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub, bool round = false)
|
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub, Vector2? mousePos = null, bool round = false)
|
||||||
{
|
{
|
||||||
Vector2 position = PlayerInput.MousePosition;
|
Vector2 position = mousePos ?? PlayerInput.MousePosition;
|
||||||
position = cam.ScreenToWorld(position);
|
position = cam.ScreenToWorld(position);
|
||||||
|
|
||||||
Vector2 worldGridPos = VectorToWorldGrid(position, round);
|
Vector2 worldGridPos = VectorToWorldGrid(position, sub, round);
|
||||||
|
|
||||||
if (sub != null)
|
|
||||||
{
|
|
||||||
worldGridPos.X += sub.Position.X % GridSize.X;
|
|
||||||
worldGridPos.Y += sub.Position.Y % GridSize.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return worldGridPos;
|
return worldGridPos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ namespace Barotrauma
|
|||||||
float scale = element.GetAttributeFloat("scale", 1f);
|
float scale = element.GetAttributeFloat("scale", 1f);
|
||||||
Color color = element.GetAttributeColor("spritecolor", Color.White);
|
Color color = element.GetAttributeColor("spritecolor", Color.White);
|
||||||
|
|
||||||
float rotation = element.GetAttributeFloat("rotation", 0f);
|
float rotationRad = MathHelper.ToRadians(element.GetAttributeFloat("rotation", 0f));
|
||||||
|
|
||||||
MapEntityPrefab prefab;
|
MapEntityPrefab prefab;
|
||||||
if (element.NameAsIdentifier() == "item"
|
if (element.NameAsIdentifier() == "item"
|
||||||
@@ -455,7 +455,7 @@ namespace Barotrauma
|
|||||||
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
||||||
if (itemPrefab != null)
|
if (itemPrefab != null)
|
||||||
{
|
{
|
||||||
BakeItemComponents(itemPrefab, rect, color, scale, rotation, depth, out overrideSprite);
|
BakeItemComponents(itemPrefab, rect, color, scale, rotationRad, depth, out overrideSprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overrideSprite)
|
if (!overrideSprite)
|
||||||
@@ -485,13 +485,15 @@ namespace Barotrauma
|
|||||||
MathUtils.PositiveModulo((int)-textureOffset.Y, prefab.Sprite.SourceRect.Height));
|
MathUtils.PositiveModulo((int)-textureOffset.Y, prefab.Sprite.SourceRect.Height));
|
||||||
|
|
||||||
prefab.Sprite.DrawTiled(
|
prefab.Sprite.DrawTiled(
|
||||||
spriteRecorder,
|
spriteBatch: spriteRecorder,
|
||||||
rect.Location.ToVector2() * new Vector2(1f, -1f),
|
position: new Vector2(rect.X + rect.Width / 2, -(rect.Y - rect.Height / 2)),
|
||||||
rect.Size.ToVector2(),
|
targetSize: rect.Size.ToVector2(),
|
||||||
|
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
|
||||||
color: color,
|
color: color,
|
||||||
startOffset: backGroundOffset,
|
startOffset: backGroundOffset,
|
||||||
textureScale: textureScale * scale,
|
textureScale: textureScale * scale,
|
||||||
depth: depth);
|
depth: depth,
|
||||||
|
rotation: rotationRad);
|
||||||
}
|
}
|
||||||
else if (itemPrefab != null)
|
else if (itemPrefab != null)
|
||||||
{
|
{
|
||||||
@@ -552,7 +554,7 @@ namespace Barotrauma
|
|||||||
spritePos * new Vector2(1f, -1f),
|
spritePos * new Vector2(1f, -1f),
|
||||||
color,
|
color,
|
||||||
prefab.Sprite.Origin,
|
prefab.Sprite.Origin,
|
||||||
rotation,
|
rotationRad,
|
||||||
scale,
|
scale,
|
||||||
prefab.Sprite.effects, depth);
|
prefab.Sprite.effects, depth);
|
||||||
|
|
||||||
@@ -564,7 +566,7 @@ namespace Barotrauma
|
|||||||
if (flippedX) { offset.X = -offset.X; }
|
if (flippedX) { offset.X = -offset.X; }
|
||||||
if (flippedY) { offset.Y = -offset.Y; }
|
if (flippedY) { offset.Y = -offset.Y; }
|
||||||
decorativeSprite.Sprite.Draw(spriteRecorder, new Vector2(spritePos.X + offset.X, -(spritePos.Y + offset.Y)), color,
|
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,
|
rotationRad + rot, decorativeSprite.GetScale(0f) * scale, prefab.Sprite.effects,
|
||||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.Sprite.Depth), 0.999f));
|
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.Sprite.Depth), 0.999f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,7 +579,7 @@ namespace Barotrauma
|
|||||||
private void BakeItemComponents(
|
private void BakeItemComponents(
|
||||||
ItemPrefab prefab,
|
ItemPrefab prefab,
|
||||||
Rectangle rect, Color color,
|
Rectangle rect, Color color,
|
||||||
float scale, float rotation, float depth,
|
float scale, float rotationRad, float depth,
|
||||||
out bool overrideSprite)
|
out bool overrideSprite)
|
||||||
{
|
{
|
||||||
overrideSprite = false;
|
overrideSprite = false;
|
||||||
@@ -607,7 +609,7 @@ namespace Barotrauma
|
|||||||
Vector2 relativeBarrelPos = barrelPos * prefab.Scale - new Vector2(rect.Width / 2, rect.Height / 2);
|
Vector2 relativeBarrelPos = barrelPos * prefab.Scale - new Vector2(rect.Width / 2, rect.Height / 2);
|
||||||
var transformedBarrelPos = MathUtils.RotatePoint(
|
var transformedBarrelPos = MathUtils.RotatePoint(
|
||||||
relativeBarrelPos,
|
relativeBarrelPos,
|
||||||
MathHelper.ToRadians(rotation));
|
rotationRad);
|
||||||
|
|
||||||
Vector2 drawPos = new Vector2(rect.X + rect.Width * relativeScale / 2 + transformedBarrelPos.X * relativeScale, rect.Y - rect.Height * relativeScale / 2 - transformedBarrelPos.Y * relativeScale);
|
Vector2 drawPos = new Vector2(rect.X + rect.Width * relativeScale / 2 + transformedBarrelPos.X * relativeScale, rect.Y - rect.Height * relativeScale / 2 - transformedBarrelPos.Y * relativeScale);
|
||||||
drawPos.Y = -drawPos.Y;
|
drawPos.Y = -drawPos.Y;
|
||||||
@@ -615,13 +617,13 @@ namespace Barotrauma
|
|||||||
railSprite?.Draw(spriteRecorder,
|
railSprite?.Draw(spriteRecorder,
|
||||||
drawPos,
|
drawPos,
|
||||||
color,
|
color,
|
||||||
rotation + MathHelper.PiOver2, scale,
|
rotationRad, scale,
|
||||||
SpriteEffects.None, depth + (railSprite.Depth - prefab.Sprite.Depth));
|
SpriteEffects.None, depth + (railSprite.Depth - prefab.Sprite.Depth));
|
||||||
|
|
||||||
barrelSprite?.Draw(spriteRecorder,
|
barrelSprite?.Draw(spriteRecorder,
|
||||||
drawPos,
|
drawPos,
|
||||||
color,
|
color,
|
||||||
rotation + MathHelper.PiOver2, scale,
|
rotationRad, scale,
|
||||||
SpriteEffects.None, depth + (barrelSprite.Depth - prefab.Sprite.Depth));
|
SpriteEffects.None, depth + (barrelSprite.Depth - prefab.Sprite.Depth));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -781,7 +783,7 @@ namespace Barotrauma
|
|||||||
previewFrame = null;
|
previewFrame = null;
|
||||||
}
|
}
|
||||||
spriteRecorder?.Dispose(); spriteRecorder = null;
|
spriteRecorder?.Dispose(); spriteRecorder = null;
|
||||||
camera?.Dispose(); camera = null;
|
camera = null;
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,12 +122,12 @@ namespace Barotrauma.Networking
|
|||||||
VoipSound = null;
|
VoipSound = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPermissions(ClientPermissions permissions, IEnumerable<string> permittedConsoleCommands)
|
public void SetPermissions(ClientPermissions permissions, IEnumerable<Identifier> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
||||||
foreach (string commandName in permittedConsoleCommands)
|
foreach (Identifier commandName in permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
var consoleCommand = DebugConsole.Commands.Find(c => c.names.Contains(commandName));
|
var consoleCommand = DebugConsole.Commands.Find(c => c.Names.Contains(commandName));
|
||||||
if (consoleCommand != null)
|
if (consoleCommand != null)
|
||||||
{
|
{
|
||||||
permittedCommands.Add(consoleCommand);
|
permittedCommands.Add(consoleCommand);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace Barotrauma.Networking
|
|||||||
public bool LateCampaignJoin = false;
|
public bool LateCampaignJoin = false;
|
||||||
|
|
||||||
private ClientPermissions permissions = ClientPermissions.None;
|
private ClientPermissions permissions = ClientPermissions.None;
|
||||||
private List<string> permittedConsoleCommands = new List<string>();
|
private List<Identifier> permittedConsoleCommands = new List<Identifier>();
|
||||||
|
|
||||||
private bool connected;
|
private bool connected;
|
||||||
|
|
||||||
@@ -170,9 +170,9 @@ namespace Barotrauma.Networking
|
|||||||
internal readonly struct PermissionChangedEvent
|
internal readonly struct PermissionChangedEvent
|
||||||
{
|
{
|
||||||
public readonly ClientPermissions NewPermissions;
|
public readonly ClientPermissions NewPermissions;
|
||||||
public readonly ImmutableArray<string> NewPermittedConsoleCommands;
|
public readonly ImmutableArray<Identifier> NewPermittedConsoleCommands;
|
||||||
|
|
||||||
public PermissionChangedEvent(ClientPermissions newPermissions, IReadOnlyList<string> newPermittedConsoleCommands)
|
public PermissionChangedEvent(ClientPermissions newPermissions, IReadOnlyList<Identifier> newPermittedConsoleCommands)
|
||||||
{
|
{
|
||||||
NewPermissions = newPermissions;
|
NewPermissions = newPermissions;
|
||||||
NewPermittedConsoleCommands = newPermittedConsoleCommands.ToImmutableArray();
|
NewPermittedConsoleCommands = newPermittedConsoleCommands.ToImmutableArray();
|
||||||
@@ -1213,11 +1213,11 @@ namespace Barotrauma.Networking
|
|||||||
targetClient?.SetPermissions(permissions, permittedCommands);
|
targetClient?.SetPermissions(permissions, permittedCommands);
|
||||||
if (clientId == SessionId)
|
if (clientId == SessionId)
|
||||||
{
|
{
|
||||||
SetMyPermissions(permissions, permittedCommands.Select(command => command.names[0]));
|
SetMyPermissions(permissions, permittedCommands.Select(command => command.Names[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetMyPermissions(ClientPermissions newPermissions, IEnumerable<string> permittedConsoleCommands)
|
private void SetMyPermissions(ClientPermissions newPermissions, IEnumerable<Identifier> permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
if (!(this.permittedConsoleCommands.Any(c => !permittedConsoleCommands.Contains(c)) ||
|
if (!(this.permittedConsoleCommands.Any(c => !permittedConsoleCommands.Contains(c)) ||
|
||||||
permittedConsoleCommands.Any(c => !this.permittedConsoleCommands.Contains(c))))
|
permittedConsoleCommands.Any(c => !this.permittedConsoleCommands.Contains(c))))
|
||||||
@@ -1229,7 +1229,7 @@ namespace Barotrauma.Networking
|
|||||||
permissions.HasFlag(ClientPermissions.ManageRound) != newPermissions.HasFlag(ClientPermissions.ManageRound);
|
permissions.HasFlag(ClientPermissions.ManageRound) != newPermissions.HasFlag(ClientPermissions.ManageRound);
|
||||||
|
|
||||||
permissions = newPermissions;
|
permissions = newPermissions;
|
||||||
this.permittedConsoleCommands = new List<string>(permittedConsoleCommands);
|
this.permittedConsoleCommands = permittedConsoleCommands.ToList();
|
||||||
//don't show the "permissions changed" popup if the client owns the server
|
//don't show the "permissions changed" popup if the client owns the server
|
||||||
if (!IsServerOwner)
|
if (!IsServerOwner)
|
||||||
{
|
{
|
||||||
@@ -1267,10 +1267,10 @@ namespace Barotrauma.Networking
|
|||||||
var commandsLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform),
|
var commandsLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform),
|
||||||
TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUIStyle.SubHeadingFont);
|
TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUIStyle.SubHeadingFont);
|
||||||
var commandList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform));
|
var commandList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform));
|
||||||
foreach (string permittedCommand in permittedConsoleCommands)
|
foreach (Identifier permittedCommand in permittedConsoleCommands)
|
||||||
{
|
{
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), commandList.Content.RectTransform, minSize: new Point(0, 15)),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), commandList.Content.RectTransform, minSize: new Point(0, 15)),
|
||||||
permittedCommand, font: GUIStyle.SmallFont)
|
permittedCommand.Value, font: GUIStyle.SmallFont)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
CanBeFocused = false
|
||||||
};
|
};
|
||||||
@@ -1350,6 +1350,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.AllowImmediateItemDelivery = inc.ReadBoolean();
|
||||||
ServerSettings.AllowFriendlyFire = inc.ReadBoolean();
|
ServerSettings.AllowFriendlyFire = inc.ReadBoolean();
|
||||||
ServerSettings.LockAllDefaultWires = inc.ReadBoolean();
|
ServerSettings.LockAllDefaultWires = inc.ReadBoolean();
|
||||||
ServerSettings.AllowLinkingWifiToChat = inc.ReadBoolean();
|
ServerSettings.AllowLinkingWifiToChat = inc.ReadBoolean();
|
||||||
@@ -2223,7 +2224,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
outmsg.WriteByte((byte)MultiplayerPreferences.Instance.TeamPreference);
|
outmsg.WriteByte((byte)MultiplayerPreferences.Instance.TeamPreference);
|
||||||
|
|
||||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.LastSaveID == 0)
|
if (GameMain.GameSession?.GameMode is not MultiPlayerCampaign campaign || campaign.LastSaveID == 0)
|
||||||
{
|
{
|
||||||
outmsg.WriteUInt16((UInt16)0);
|
outmsg.WriteUInt16((UInt16)0);
|
||||||
}
|
}
|
||||||
@@ -2553,18 +2554,18 @@ namespace Barotrauma.Networking
|
|||||||
return permissions.HasFlag(permission);
|
return permissions.HasFlag(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasConsoleCommandPermission(string commandName)
|
public bool HasConsoleCommandPermission(Identifier commandName)
|
||||||
{
|
{
|
||||||
if (!permissions.HasFlag(ClientPermissions.ConsoleCommands)) { return false; }
|
if (!permissions.HasFlag(ClientPermissions.ConsoleCommands)) { return false; }
|
||||||
|
|
||||||
if (permittedConsoleCommands.Any(c => c.Equals(commandName, StringComparison.OrdinalIgnoreCase))) { return true; }
|
if (permittedConsoleCommands.Contains(commandName)) { return true; }
|
||||||
|
|
||||||
//check aliases
|
//check aliases
|
||||||
foreach (DebugConsole.Command command in DebugConsole.Commands)
|
foreach (DebugConsole.Command command in DebugConsole.Commands)
|
||||||
{
|
{
|
||||||
if (command.names.Contains(commandName))
|
if (command.Names.Contains(commandName))
|
||||||
{
|
{
|
||||||
if (command.names.Intersect(permittedConsoleCommands).Any()) { return true; }
|
if (command.Names.Intersect(permittedConsoleCommands).Any()) { return true; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ namespace Barotrauma.Networking
|
|||||||
[Serialize("", IsPropertySaveable.Yes)]
|
[Serialize("", IsPropertySaveable.Yes)]
|
||||||
public LanguageIdentifier Language { get; set; }
|
public LanguageIdentifier Language { get; set; }
|
||||||
|
|
||||||
|
[Serialize("", IsPropertySaveable.Yes)]
|
||||||
|
public string SelectedSub { get; set; } = string.Empty;
|
||||||
|
|
||||||
public Version GameVersion { get; set; } = new Version(0, 0, 0, 0);
|
public Version GameVersion { get; set; } = new Version(0, 0, 0, 0);
|
||||||
|
|
||||||
public Option<int> Ping = Option<int>.None();
|
public Option<int> Ping = Option<int>.None();
|
||||||
@@ -104,6 +107,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public ImmutableArray<ContentPackageInfo> ContentPackages;
|
public ImmutableArray<ContentPackageInfo> ContentPackages;
|
||||||
|
|
||||||
|
public int ContentPackageCount;
|
||||||
|
|
||||||
public bool IsModded => ContentPackages.Any(p => !GameMain.VanillaContent.NameMatches(p.Name));
|
public bool IsModded => ContentPackages.Any(p => !GameMain.VanillaContent.NameMatches(p.Name));
|
||||||
|
|
||||||
public ServerInfo(Endpoint endpoint)
|
public ServerInfo(Endpoint endpoint)
|
||||||
@@ -176,33 +181,6 @@ namespace Barotrauma.Networking
|
|||||||
};
|
};
|
||||||
title.Text = ToolBox.LimitString(title.Text, title.Font, (int)(title.Rect.Width * 0.85f));
|
title.Text = ToolBox.LimitString(title.Text, title.Font, (int)(title.Rect.Width * 0.85f));
|
||||||
|
|
||||||
bool isFavorite = serverListScreen.IsFavorite(this);
|
|
||||||
|
|
||||||
static LocalizedString favoriteTickBoxToolTip(bool isFavorite)
|
|
||||||
=> TextManager.Get(isFavorite ? "RemoveFromFavorites" : "AddToFavorites");
|
|
||||||
|
|
||||||
GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.8f), title.RectTransform, Anchor.CenterRight),
|
|
||||||
"", null, "GUIServerListFavoriteTickBox")
|
|
||||||
{
|
|
||||||
UserData = this,
|
|
||||||
Selected = isFavorite,
|
|
||||||
ToolTip = favoriteTickBoxToolTip(isFavorite),
|
|
||||||
OnSelected = tickbox =>
|
|
||||||
{
|
|
||||||
ServerInfo info = (ServerInfo)tickbox.UserData;
|
|
||||||
if (tickbox.Selected)
|
|
||||||
{
|
|
||||||
GameMain.ServerListScreen.AddToFavoriteServers(info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GameMain.ServerListScreen.RemoveFromFavoriteServers(info);
|
|
||||||
}
|
|
||||||
tickbox.ToolTip = favoriteTickBoxToolTip(tickbox.Selected);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"),
|
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"),
|
||||||
GameVersion == new Version(0, 0, 0, 0) ? TextManager.Get("Unknown") : GameVersion.ToString()))
|
GameVersion == new Version(0, 0, 0, 0) ? TextManager.Get("Unknown") : GameVersion.ToString()))
|
||||||
@@ -258,6 +236,59 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 0.25f), playStyleBanner.RectTransform, Anchor.BottomRight),
|
||||||
|
isHorizontal: true, childAnchor: Anchor.BottomRight);
|
||||||
|
|
||||||
|
//shadow behind the buttons
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(3.15f, 1.05f), buttonContainer.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest), style: null)
|
||||||
|
{
|
||||||
|
Color = Color.Black * 0.7f,
|
||||||
|
IgnoreLayoutGroups = true
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isFavorite = serverListScreen.IsFavorite(this);
|
||||||
|
static LocalizedString favoriteTickBoxToolTip(bool isFavorite)
|
||||||
|
=> TextManager.Get(isFavorite ? "RemoveFromFavorites" : "AddToFavorites");
|
||||||
|
|
||||||
|
GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.Smallest),
|
||||||
|
"", null, "GUIServerListFavoriteTickBox")
|
||||||
|
{
|
||||||
|
UserData = this,
|
||||||
|
Selected = isFavorite,
|
||||||
|
ToolTip = favoriteTickBoxToolTip(isFavorite),
|
||||||
|
OnSelected = tickbox =>
|
||||||
|
{
|
||||||
|
ServerInfo info = (ServerInfo)tickbox.UserData;
|
||||||
|
if (tickbox.Selected)
|
||||||
|
{
|
||||||
|
GameMain.ServerListScreen.AddToFavoriteServers(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.ServerListScreen.RemoveFromFavoriteServers(info);
|
||||||
|
}
|
||||||
|
tickbox.ToolTip = favoriteTickBoxToolTip(tickbox.Selected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "GUIServerListReportServer")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("reportserver"),
|
||||||
|
OnClicked = (_, _) => {ServerListScreen.CreateReportPrompt(this); return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "GUIServerListHideServer")
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("filterserver"),
|
||||||
|
OnClicked = (_, _) =>
|
||||||
|
{
|
||||||
|
ServerListScreen.CreateFilterServerPrompt(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// playstyle tags -----------------------------------------------------------------------------
|
// playstyle tags -----------------------------------------------------------------------------
|
||||||
|
|
||||||
var playStyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), isHorizontal: true)
|
var playStyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), isHorizontal: true)
|
||||||
@@ -309,6 +340,14 @@ namespace Barotrauma.Networking
|
|||||||
TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value),
|
TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value),
|
||||||
textAlignment: Alignment.Right);
|
textAlignment: Alignment.Right);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(SelectedSub))
|
||||||
|
{
|
||||||
|
var submarineText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("Submarine"));
|
||||||
|
new GUITextBlock(new RectTransform(Vector2.One, submarineText.RectTransform),
|
||||||
|
SelectedSub,
|
||||||
|
textAlignment: Alignment.Right);
|
||||||
|
}
|
||||||
|
|
||||||
GUITextBlock playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle"));
|
GUITextBlock playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle"));
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right);
|
new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right);
|
||||||
|
|
||||||
@@ -385,6 +424,15 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ContentPackageCount > ContentPackages.Length)
|
||||||
|
{
|
||||||
|
new GUITextBlock(
|
||||||
|
new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||||
|
TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (ContentPackageCount - ContentPackages.Length).ToString()))
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -423,14 +471,16 @@ namespace Barotrauma.Networking
|
|||||||
AllowSpectating = getBool("allowspectating");
|
AllowSpectating = getBool("allowspectating");
|
||||||
AllowRespawn = getBool("allowrespawn");
|
AllowRespawn = getBool("allowrespawn");
|
||||||
VoipEnabled = getBool("voicechatenabled");
|
VoipEnabled = getBool("voicechatenabled");
|
||||||
|
|
||||||
GameMode = valueGetter("gamemode")?.ToIdentifier() ?? Identifier.Empty;
|
GameMode = valueGetter("gamemode")?.ToIdentifier() ?? Identifier.Empty;
|
||||||
if (float.TryParse(valueGetter("traitors"), NumberStyles.Any, CultureInfo.InvariantCulture, out float traitorProbability)) { TraitorProbability = traitorProbability; }
|
if (float.TryParse(valueGetter("traitors"), NumberStyles.Any, CultureInfo.InvariantCulture, out float traitorProbability)) { TraitorProbability = traitorProbability; }
|
||||||
if (Enum.TryParse(valueGetter("playstyle"), out PlayStyle playStyle)) { PlayStyle = playStyle; }
|
if (Enum.TryParse(valueGetter("playstyle"), out PlayStyle playStyle)) { PlayStyle = playStyle; }
|
||||||
Language = valueGetter("language")?.ToLanguageIdentifier() ?? LanguageIdentifier.None;
|
Language = valueGetter("language")?.ToLanguageIdentifier() ?? LanguageIdentifier.None;
|
||||||
|
SelectedSub = valueGetter("submarine") ?? string.Empty;
|
||||||
|
|
||||||
ContentPackages = ExtractContentPackageInfo(ServerName, valueGetter).ToImmutableArray();
|
ContentPackages = ExtractContentPackageInfo(ServerName, valueGetter).ToImmutableArray();
|
||||||
|
ContentPackageCount = ContentPackages.Length;
|
||||||
|
if (int.TryParse(valueGetter("packagecount"), out int packageCount)) { ContentPackageCount = packageCount; }
|
||||||
|
|
||||||
bool getBool(string key)
|
bool getBool(string key)
|
||||||
{
|
{
|
||||||
string? data = valueGetter(key);
|
string? data = valueGetter(key);
|
||||||
|
|||||||
@@ -936,6 +936,10 @@ namespace Barotrauma.Networking
|
|||||||
TextManager.Get("ServerSettingsAllowVoteKick"));
|
TextManager.Get("ServerSettingsAllowVoteKick"));
|
||||||
GetPropertyData(nameof(AllowVoteKick)).AssignGUIComponent(voteKickBox);
|
GetPropertyData(nameof(AllowVoteKick)).AssignGUIComponent(voteKickBox);
|
||||||
|
|
||||||
|
var allowImmediateItemDeliveryBox = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
|
||||||
|
TextManager.Get("ServerSettingsImmediateItemDelivery"));
|
||||||
|
GetPropertyData(nameof(AllowImmediateItemDelivery)).AssignGUIComponent(allowImmediateItemDeliveryBox);
|
||||||
|
|
||||||
GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
|
GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
|
||||||
|
|
||||||
tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
|
tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
#nullable enable
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@@ -148,7 +149,7 @@ namespace Barotrauma.Particles
|
|||||||
Prefab = prefab;
|
Prefab = prefab;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
|
public void Emit(float deltaTime, Vector2 position, Hull? hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab? overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2>? tracerPoints = null)
|
||||||
{
|
{
|
||||||
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||||
|
|
||||||
@@ -191,16 +192,17 @@ namespace Barotrauma.Particles
|
|||||||
burstEmitTimer = Prefab.Properties.EmitInterval;
|
burstEmitTimer = Prefab.Properties.EmitInterval;
|
||||||
for (int i = 0; i < Prefab.Properties.ParticleAmount * amountMultiplier; i++)
|
for (int i = 0; i < Prefab.Properties.ParticleAmount * amountMultiplier; i++)
|
||||||
{
|
{
|
||||||
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: tracerPoints);
|
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, mirrorAngle, tracerPoints: tracerPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
|
private void Emit(Vector2 position, Hull? hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab? overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2>? tracerPoints = null)
|
||||||
{
|
{
|
||||||
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
|
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
|
||||||
if (particlePrefab == null)
|
if (particlePrefab == null)
|
||||||
{
|
{
|
||||||
DebugConsole.AddWarning($"Could not find the particle prefab \"{Prefab.ParticlePrefabName}\".");
|
DebugConsole.AddWarning($"Could not find the particle prefab \"{Prefab.ParticlePrefabName}\".",
|
||||||
|
contentPackage: Prefab.ContentPackage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ namespace Barotrauma.Particles
|
|||||||
{
|
{
|
||||||
public readonly Identifier ParticlePrefabName;
|
public readonly Identifier ParticlePrefabName;
|
||||||
|
|
||||||
public ParticlePrefab ParticlePrefab
|
public ParticlePrefab? ParticlePrefab
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -282,12 +284,16 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public readonly ParticleEmitterProperties Properties;
|
public readonly ParticleEmitterProperties Properties;
|
||||||
|
|
||||||
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab.DrawOnTop;
|
public readonly ContentPackage? ContentPackage;
|
||||||
|
|
||||||
|
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab is { DrawOnTop: true };
|
||||||
|
|
||||||
public ParticleEmitterPrefab(ContentXElement element)
|
public ParticleEmitterPrefab(ContentXElement element)
|
||||||
{
|
{
|
||||||
Properties = new ParticleEmitterProperties(element);
|
if (element == null) { throw new ArgumentNullException(nameof(element)); }
|
||||||
|
Properties = new ParticleEmitterProperties(element!);
|
||||||
ParticlePrefabName = element.GetAttributeIdentifier("particle", "");
|
ParticlePrefabName = element.GetAttributeIdentifier("particle", "");
|
||||||
|
ContentPackage = element.ContentPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParticleEmitterPrefab(ParticlePrefab prefab, ParticleEmitterProperties properties)
|
public ParticleEmitterPrefab(ParticlePrefab prefab, ParticleEmitterProperties properties)
|
||||||
|
|||||||
@@ -244,7 +244,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
if (Sprites.Count == 0)
|
if (Sprites.Count == 0)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Particle prefab \"{Name}\" in the file \"{file}\" has no sprites defined!");
|
DebugConsole.ThrowError($"Particle prefab \"{Name}\" in the file \"{file}\" has no sprites defined!",
|
||||||
|
contentPackage: element.ContentPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if velocity change in water is not given, it defaults to the normal velocity change
|
//if velocity change in water is not given, it defaults to the normal velocity change
|
||||||
|
|||||||
@@ -66,15 +66,22 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static void CrashHandler(object sender, UnhandledExceptionEventArgs args)
|
private static void CrashHandler(object sender, UnhandledExceptionEventArgs args)
|
||||||
{
|
{
|
||||||
|
Exception unhandledException = args.ExceptionObject as Exception;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game?.Exit();
|
Game?.Exit();
|
||||||
CrashDump(Game, "crashreport.log", (Exception)args.ExceptionObject);
|
CrashDump(Game, "crashreport.log", unhandledException);
|
||||||
Game?.Dispose();
|
Game?.Dispose();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception exceptionHandlerError)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(e.Message);
|
Debug.WriteLine(exceptionHandlerError.Message);
|
||||||
|
string slimCrashReport = "Exception handler failed: " + exceptionHandlerError.Message + "\n" + exceptionHandlerError.StackTrace;
|
||||||
|
if (unhandledException != null)
|
||||||
|
{
|
||||||
|
slimCrashReport += "\n\nInitial exception: " + unhandledException.Message + "\n" + unhandledException.StackTrace;
|
||||||
|
}
|
||||||
|
File.WriteAllText("crashreportslim.log", slimCrashReport);
|
||||||
//exception handler is broken, we have a serious problem here!!
|
//exception handler is broken, we have a serious problem here!!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ namespace Barotrauma
|
|||||||
public CampaignMode Campaign { get; }
|
public CampaignMode Campaign { get; }
|
||||||
|
|
||||||
public CrewManagement CrewManagement { get; set; }
|
public CrewManagement CrewManagement { get; set; }
|
||||||
private Store Store { get; set; }
|
|
||||||
|
public Store Store { get; private set; }
|
||||||
|
|
||||||
public UpgradeStore UpgradeStore { get; set; }
|
public UpgradeStore UpgradeStore { get; set; }
|
||||||
|
|
||||||
@@ -254,7 +255,7 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.02f,
|
RelativeSpacing = 0.02f,
|
||||||
};
|
};
|
||||||
|
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Name, font: GUIStyle.LargeFont)
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.DisplayName, font: GUIStyle.LargeFont)
|
||||||
{
|
{
|
||||||
AutoScaleHorizontal = true
|
AutoScaleHorizontal = true
|
||||||
};
|
};
|
||||||
@@ -598,9 +599,10 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case CampaignMode.InteractionType.Crew:
|
case CampaignMode.InteractionType.Crew:
|
||||||
CrewManagement.UpdateCrew();
|
CrewManagement.UpdateCrew();
|
||||||
|
CrewManagement.UpdateHireables();
|
||||||
break;
|
break;
|
||||||
case CampaignMode.InteractionType.PurchaseSub:
|
case CampaignMode.InteractionType.PurchaseSub:
|
||||||
if (submarineSelection == null) submarineSelection = new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
|
submarineSelection ??= new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
|
||||||
submarineSelection.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
|
submarineSelection.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
|
||||||
break;
|
break;
|
||||||
case CampaignMode.InteractionType.Map:
|
case CampaignMode.InteractionType.Map:
|
||||||
|
|||||||
@@ -259,8 +259,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
graphics.BlendState = BlendState.NonPremultiplied;
|
graphics.BlendState = BlendState.NonPremultiplied;
|
||||||
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
||||||
Quad.UseBasicEffect(renderTargetBackground);
|
GraphicsQuad.UseBasicEffect(renderTargetBackground);
|
||||||
Quad.Render();
|
GraphicsQuad.Render();
|
||||||
|
|
||||||
//Draw the rest of the structures, characters and front structures
|
//Draw the rest of the structures, characters and front structures
|
||||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||||
@@ -313,8 +313,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
graphics.BlendState = BlendState.Opaque;
|
graphics.BlendState = BlendState.Opaque;
|
||||||
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
||||||
Quad.UseBasicEffect(renderTarget);
|
GraphicsQuad.UseBasicEffect(renderTarget);
|
||||||
Quad.Render();
|
GraphicsQuad.Render();
|
||||||
|
|
||||||
//draw alpha blended particles that are inside a sub
|
//draw alpha blended particles that are inside a sub
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
||||||
@@ -380,8 +380,8 @@ namespace Barotrauma
|
|||||||
graphics.DepthStencilState = DepthStencilState.None;
|
graphics.DepthStencilState = DepthStencilState.None;
|
||||||
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
||||||
graphics.BlendState = CustomBlendStates.Multiplicative;
|
graphics.BlendState = CustomBlendStates.Multiplicative;
|
||||||
Quad.UseBasicEffect(GameMain.LightManager.LightMap);
|
GraphicsQuad.UseBasicEffect(GameMain.LightManager.LightMap);
|
||||||
Quad.Render();
|
GraphicsQuad.Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
|
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
|
||||||
@@ -390,6 +390,8 @@ namespace Barotrauma
|
|||||||
c.DrawFront(spriteBatch, cam);
|
c.DrawFront(spriteBatch, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameMain.LightManager.DebugDrawVertices(spriteBatch);
|
||||||
|
|
||||||
Level.Loaded?.DrawDebugOverlay(spriteBatch, cam);
|
Level.Loaded?.DrawDebugOverlay(spriteBatch, cam);
|
||||||
if (GameMain.DebugDraw)
|
if (GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
@@ -438,7 +440,7 @@ namespace Barotrauma
|
|||||||
graphics.SamplerStates[0] = SamplerState.PointClamp;
|
graphics.SamplerStates[0] = SamplerState.PointClamp;
|
||||||
graphics.SamplerStates[1] = SamplerState.PointClamp;
|
graphics.SamplerStates[1] = SamplerState.PointClamp;
|
||||||
GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply();
|
GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
Quad.Render();
|
GraphicsQuad.Render();
|
||||||
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
graphics.SamplerStates[0] = SamplerState.LinearWrap;
|
||||||
graphics.SamplerStates[1] = SamplerState.LinearWrap;
|
graphics.SamplerStates[1] = SamplerState.LinearWrap;
|
||||||
}
|
}
|
||||||
@@ -506,7 +508,7 @@ namespace Barotrauma
|
|||||||
graphics.DepthStencilState = DepthStencilState.None;
|
graphics.DepthStencilState = DepthStencilState.None;
|
||||||
if (string.IsNullOrEmpty(postProcessTechnique))
|
if (string.IsNullOrEmpty(postProcessTechnique))
|
||||||
{
|
{
|
||||||
Quad.UseBasicEffect(renderTargetFinal);
|
GraphicsQuad.UseBasicEffect(renderTargetFinal);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -515,7 +517,7 @@ namespace Barotrauma
|
|||||||
PostProcessEffect.CurrentTechnique = PostProcessEffect.Techniques[postProcessTechnique];
|
PostProcessEffect.CurrentTechnique = PostProcessEffect.Techniques[postProcessTechnique];
|
||||||
PostProcessEffect.CurrentTechnique.Passes[0].Apply();
|
PostProcessEffect.CurrentTechnique.Passes[0].Apply();
|
||||||
}
|
}
|
||||||
Quad.Render();
|
GraphicsQuad.Render();
|
||||||
|
|
||||||
if (fadeToBlackState > 0.0f)
|
if (fadeToBlackState > 0.0f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -221,7 +221,17 @@ namespace Barotrauma
|
|||||||
currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
|
currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
|
||||||
var dummyLocations = GameSession.CreateDummyLocations(currentLevelData);
|
var dummyLocations = GameSession.CreateDummyLocations(currentLevelData);
|
||||||
Level.Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
|
Level.Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
|
||||||
Submarine.MainSub?.SetPosition(Level.Loaded.StartPosition);
|
|
||||||
|
if (Submarine.MainSub != null)
|
||||||
|
{
|
||||||
|
Vector2 startPos = Level.Loaded.StartPosition;
|
||||||
|
if (Level.Loaded.StartOutpost != null)
|
||||||
|
{
|
||||||
|
startPos.Y -= Level.Loaded.StartOutpost.Borders.Height / 2 + Submarine.MainSub.Borders.Height / 2;
|
||||||
|
}
|
||||||
|
Submarine.MainSub?.SetPosition(startPos);
|
||||||
|
}
|
||||||
|
|
||||||
GameMain.LightManager.AddLight(pointerLightSource);
|
GameMain.LightManager.AddLight(pointerLightSource);
|
||||||
if (!wasLevelLoaded || Cam.Position.X < 0 || Cam.Position.Y < 0 || Cam.Position.Y > Level.Loaded.Size.X || Cam.Position.Y > Level.Loaded.Size.Y)
|
if (!wasLevelLoaded || Cam.Position.X < 0 || Cam.Position.Y < 0 || Cam.Position.Y > Level.Loaded.Size.X || Cam.Position.Y > Level.Loaded.Size.Y)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ namespace Barotrauma
|
|||||||
private GUITextBlock tutorialHeader, tutorialDescription;
|
private GUITextBlock tutorialHeader, tutorialDescription;
|
||||||
private GUIListBox tutorialList;
|
private GUIListBox tutorialList;
|
||||||
|
|
||||||
|
private GUIComponent versionMismatchWarning;
|
||||||
|
|
||||||
#region Creation
|
#region Creation
|
||||||
public MainMenuScreen(GameMain game)
|
public MainMenuScreen(GameMain game)
|
||||||
{
|
{
|
||||||
@@ -105,6 +107,28 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
versionMismatchWarning = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.065f), Frame.RectTransform) { AbsoluteOffset = new Point(GUI.IntScale(15)) }, style: "InnerFrame", color: GUIStyle.Red)
|
||||||
|
{
|
||||||
|
IgnoreLayoutGroups = true,
|
||||||
|
Visible = false
|
||||||
|
};
|
||||||
|
var versionMismatchContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), versionMismatchWarning.RectTransform, Anchor.Center), isHorizontal: true)
|
||||||
|
{
|
||||||
|
RelativeSpacing = 0.05f,
|
||||||
|
};
|
||||||
|
new GUIImage(new RectTransform(new Vector2(1.0f), versionMismatchContent.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "GUINotificationButton")
|
||||||
|
{
|
||||||
|
Color = GUIStyle.Orange
|
||||||
|
};
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), versionMismatchContent.RectTransform),
|
||||||
|
TextManager.GetWithVariables("versionmismatchwarning",
|
||||||
|
("[gameversion]", GameMain.Version.ToString()),
|
||||||
|
("[contentversion]", ContentPackageManager.VanillaCorePackage.GameVersion.ToString())),
|
||||||
|
wrap: true)
|
||||||
|
{
|
||||||
|
TextColor = GUIStyle.Orange
|
||||||
|
};
|
||||||
|
|
||||||
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
|
||||||
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
|
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
|
||||||
style: "TitleText")
|
style: "TitleText")
|
||||||
@@ -141,6 +165,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
SpamServerFilters.RequestGlobalSpamFilter();
|
||||||
FetchRemoteContent();
|
FetchRemoteContent();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -607,7 +632,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GameMain.SubEditorScreen?.ClearBackedUpSubInfo();
|
GameMain.SubEditorScreen?.ClearBackedUpSubInfo();
|
||||||
Submarine.Unload();
|
Submarine.Unload();
|
||||||
|
|
||||||
|
versionMismatchWarning.Visible = GameMain.Version < ContentPackageManager.VanillaCorePackage.GameVersion;
|
||||||
|
|
||||||
ResetButtonStates(null);
|
ResetButtonStates(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +710,18 @@ namespace Barotrauma
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
foreach (var newServerExe in newServerExes)
|
foreach (var newServerExe in newServerExes)
|
||||||
{
|
{
|
||||||
serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
|
var serverExeEntry = serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
|
||||||
|
if (newServerExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
|
||||||
|
{
|
||||||
|
serverExeEntry.ToolTip =
|
||||||
|
TextManager.GetWithVariables("versionmismatchwarning",
|
||||||
|
("[gameversion]", newServerExe.ContentPackage.GameVersion.ToString()),
|
||||||
|
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString()));
|
||||||
|
if (serverExeEntry is GUITextBlock serverExeText)
|
||||||
|
{
|
||||||
|
serverExeText.TextColor = GUIStyle.Red;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serverExecutableDropdown.ListBox.Content.Children.ForEach(c =>
|
serverExecutableDropdown.ListBox.Content.Children.ForEach(c =>
|
||||||
{
|
{
|
||||||
@@ -1496,34 +1534,58 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
string name = serverNameBox.Text;
|
CheckServerName();
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
serverNameBox.Flash();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
|
|
||||||
{
|
|
||||||
var msgBox = new GUIMessageBox("",
|
|
||||||
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
|
|
||||||
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
|
|
||||||
msgBox.Buttons[0].OnClicked += (_, __) =>
|
|
||||||
{
|
|
||||||
TryStartServer();
|
|
||||||
msgBox.Close();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TryStartServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void CheckServerName()
|
||||||
|
{
|
||||||
|
string name = serverNameBox.Text;
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
serverNameBox.Flash();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
|
||||||
|
{
|
||||||
|
var msgBox = new GUIMessageBox("",
|
||||||
|
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
|
||||||
|
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
msgBox.Buttons[0].OnClicked += (_, __) =>
|
||||||
|
{
|
||||||
|
CheckServerExe();
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CheckServerExe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckServerExe()
|
||||||
|
{
|
||||||
|
if (serverExecutableDropdown?.SelectedData is ServerExecutableFile serverExe &&
|
||||||
|
serverExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
|
||||||
|
{
|
||||||
|
var msgBox = new GUIMessageBox(string.Empty,
|
||||||
|
TextManager.GetWithVariables("versionmismatchwarning",
|
||||||
|
("[gameversion]", serverExe.ContentPackage.GameVersion.ToString()),
|
||||||
|
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString())) + "\n\n"+
|
||||||
|
TextManager.GetWithVariable("versionmismatch.verifylaunch", "[exename]", serverExe.ContentPackage.Name),
|
||||||
|
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
|
||||||
|
msgBox.Buttons[0].OnClicked += (_, __) =>
|
||||||
|
{
|
||||||
|
TryStartServer();
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TryStartServer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetServerPlayStyle(PlayStyle playStyle)
|
private void SetServerPlayStyle(PlayStyle playStyle)
|
||||||
|
|||||||
@@ -1520,6 +1520,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool nameChangePending = isGameRunning && GameMain.Client.PendingName != string.Empty && GameMain.Client?.Character?.Name != GameMain.Client.PendingName;
|
bool nameChangePending = isGameRunning && GameMain.Client.PendingName != string.Empty && GameMain.Client?.Character?.Name != GameMain.Client.PendingName;
|
||||||
|
changesPendingText?.Parent?.RemoveChild(changesPendingText);
|
||||||
changesPendingText = null;
|
changesPendingText = null;
|
||||||
|
|
||||||
if (TabMenu.PendingChanges)
|
if (TabMenu.PendingChanges)
|
||||||
@@ -2389,10 +2390,20 @@ namespace Barotrauma
|
|||||||
options.Add(kickOption);
|
options.Add(kickOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
|
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(client)) ?? false)
|
||||||
{
|
{
|
||||||
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
options.Add(new ContextMenuOption("clientpermission.unban", isEnabled: canBan, onSelected: delegate
|
||||||
}));
|
{
|
||||||
|
GameMain.Client?.UnbanPlayer(client.Name);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
|
||||||
|
{
|
||||||
|
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
|
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
|
||||||
}
|
}
|
||||||
@@ -2591,11 +2602,11 @@ namespace Barotrauma
|
|||||||
foreach (DebugConsole.Command command in DebugConsole.Commands)
|
foreach (DebugConsole.Command command in DebugConsole.Commands)
|
||||||
{
|
{
|
||||||
var commandTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.15f), commandList.Content.RectTransform),
|
var commandTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.15f), commandList.Content.RectTransform),
|
||||||
command.names[0], font: GUIStyle.SmallFont)
|
command.Names[0].Value, font: GUIStyle.SmallFont)
|
||||||
{
|
{
|
||||||
Selected = selectedClient.PermittedConsoleCommands.Contains(command),
|
Selected = selectedClient.PermittedConsoleCommands.Contains(command),
|
||||||
Enabled = !myClient,
|
Enabled = !myClient,
|
||||||
ToolTip = command.help,
|
ToolTip = command.Help,
|
||||||
UserData = command
|
UserData = command
|
||||||
};
|
};
|
||||||
commandTickBox.OnSelected += (GUITickBox tickBox) =>
|
commandTickBox.OnSelected += (GUITickBox tickBox) =>
|
||||||
@@ -2630,12 +2641,25 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.Client.HasPermission(ClientPermissions.Ban))
|
if (GameMain.Client.HasPermission(ClientPermissions.Ban))
|
||||||
{
|
{
|
||||||
var banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
|
GUIButton banButton;
|
||||||
TextManager.Get("Ban"))
|
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(selectedClient)) ?? false)
|
||||||
{
|
{
|
||||||
UserData = selectedClient
|
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
|
||||||
};
|
TextManager.Get("clientpermission.unban"))
|
||||||
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
|
{
|
||||||
|
UserData = selectedClient
|
||||||
|
};
|
||||||
|
banButton.OnClicked = (bt, userdata) => { GameMain.Client?.UnbanPlayer(selectedClient.Name); return true; };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
|
||||||
|
TextManager.Get("Ban"))
|
||||||
|
{
|
||||||
|
UserData = selectedClient
|
||||||
|
};
|
||||||
|
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
|
||||||
|
}
|
||||||
banButton.OnClicked += ClosePlayerFrame;
|
banButton.OnClicked += ClosePlayerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3147,12 +3171,12 @@ namespace Barotrauma
|
|||||||
GUIButton jobButton = null;
|
GUIButton jobButton = null;
|
||||||
|
|
||||||
var availableJobs = JobPrefab.Prefabs.Where(jobPrefab =>
|
var availableJobs = JobPrefab.Prefabs.Where(jobPrefab =>
|
||||||
jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => !(c.UserData is JobVariant prefab) || prefab.Prefab != jobPrefab)
|
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => c.UserData is not JobVariant prefab || prefab.Prefab != jobPrefab)
|
||||||
).Select(j => new JobVariant(j, 0));
|
).Select(j => new JobVariant(j, 0));
|
||||||
|
|
||||||
availableJobs = availableJobs.Concat(
|
availableJobs = availableJobs.Concat(
|
||||||
JobPrefab.Prefabs.Where(jobPrefab =>
|
JobPrefab.Prefabs.Where(jobPrefab =>
|
||||||
jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
|
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
|
||||||
).Select(j => (JobVariant)JobList.Content.FindChild(c => (c.UserData is JobVariant prefab) && prefab.Prefab == j).UserData));
|
).Select(j => (JobVariant)JobList.Content.FindChild(c => (c.UserData is JobVariant prefab) && prefab.Prefab == j).UserData));
|
||||||
|
|
||||||
availableJobs = availableJobs.ToList();
|
availableJobs = availableJobs.ToList();
|
||||||
|
|||||||
+175
-13
@@ -655,7 +655,8 @@ namespace Barotrauma
|
|||||||
ScrollBarVisible = true,
|
ScrollBarVisible = true,
|
||||||
OnSelected = (btn, obj) =>
|
OnSelected = (btn, obj) =>
|
||||||
{
|
{
|
||||||
if (!(obj is ServerInfo serverInfo)) { return false; }
|
if (GUI.MouseOn is GUIButton) { return false; }
|
||||||
|
if (obj is not ServerInfo serverInfo) { return false; }
|
||||||
|
|
||||||
joinButton.Enabled = true;
|
joinButton.Enabled = true;
|
||||||
selectedServer = Option<ServerInfo>.Some(serverInfo);
|
selectedServer = Option<ServerInfo>.Some(serverInfo);
|
||||||
@@ -852,6 +853,13 @@ namespace Barotrauma
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void HideServerPreview()
|
||||||
|
{
|
||||||
|
serverPreviewContainer.Visible = false;
|
||||||
|
panelAnimator.RightEnabled = false;
|
||||||
|
panelAnimator.RightVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void InsertServer(ServerInfo serverInfo, GUIComponent component)
|
private void InsertServer(ServerInfo serverInfo, GUIComponent component)
|
||||||
{
|
{
|
||||||
var children = serverList.Content.RectTransform.Children.Reverse().ToList();
|
var children = serverList.Content.RectTransform.Children.Reverse().ToList();
|
||||||
@@ -973,7 +981,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterServers()
|
public void FilterServers()
|
||||||
{
|
{
|
||||||
RemoveMsgFromServerList(MsgUserData.NoMatchingServers);
|
RemoveMsgFromServerList(MsgUserData.NoMatchingServers);
|
||||||
foreach (GUIComponent child in serverList.Content.Children)
|
foreach (GUIComponent child in serverList.Content.Children)
|
||||||
@@ -1013,6 +1021,7 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (SpamServerFilters.IsFiltered(serverInfo)) { return false; }
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(searchBox.Text) && !serverInfo.ServerName.Contains(searchBox.Text, StringComparison.OrdinalIgnoreCase)) { return false; }
|
if (!string.IsNullOrEmpty(searchBox.Text) && !serverInfo.ServerName.Contains(searchBox.Text, StringComparison.OrdinalIgnoreCase)) { return false; }
|
||||||
|
|
||||||
@@ -1553,15 +1562,169 @@ namespace Barotrauma
|
|||||||
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) },
|
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) },
|
||||||
style: "ListBoxElement")
|
style: "ListBoxElement")
|
||||||
{
|
{
|
||||||
UserData = serverInfo
|
UserData = serverInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
serverFrame.OnSecondaryClicked += (_, data) =>
|
||||||
|
{
|
||||||
|
if (data is not ServerInfo info) { return false; }
|
||||||
|
CreateContextMenu(info);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
{
|
{
|
||||||
Stretch = false
|
Stretch = false
|
||||||
};
|
};
|
||||||
UpdateServerInfoUI(serverInfo);
|
UpdateServerInfoUI(serverInfo);
|
||||||
if (!skipPing) { PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); }
|
if (!skipPing) { PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Vector2 confirmPopupSize = new Vector2(0.2f, 0.2625f);
|
||||||
|
private static readonly Point confirmPopupMinSize = new Point(300, 300);
|
||||||
|
|
||||||
|
private void CreateContextMenu(ServerInfo info)
|
||||||
|
{
|
||||||
|
var favoriteOption = new ContextMenuOption(IsFavorite(info) ? "removefromfavorites" : "addtofavorites", isEnabled: true, () =>
|
||||||
|
{
|
||||||
|
if (IsFavorite(info))
|
||||||
|
{
|
||||||
|
RemoveFromFavoriteServers(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddToFavoriteServers(info);
|
||||||
|
}
|
||||||
|
FilterServers();
|
||||||
|
});
|
||||||
|
var reportOption = new ContextMenuOption("reportserver", isEnabled: true, () => { CreateReportPrompt(info); });
|
||||||
|
var filterOption = new ContextMenuOption("filterserver", isEnabled: true, () =>
|
||||||
|
{
|
||||||
|
CreateFilterServerPrompt(info);
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Tooltip = TextManager.Get("filterservertooltip")
|
||||||
|
};
|
||||||
|
|
||||||
|
GUIContextMenu.CreateContextMenu(favoriteOption, filterOption, reportOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateFilterServerPrompt(ServerInfo info)
|
||||||
|
{
|
||||||
|
GUI.AskForConfirmation(
|
||||||
|
header: TextManager.Get("filterserver"),
|
||||||
|
body: TextManager.GetWithVariables("filterserverconfirm", ("[server]", info.ServerName), ("[filepath]", SpamServerFilter.SavePath)),
|
||||||
|
onConfirm: () =>
|
||||||
|
{
|
||||||
|
SpamServerFilters.AddServerToLocalSpamList(info);
|
||||||
|
|
||||||
|
if (GameMain.ServerListScreen is not { } serverListScreen) { return; }
|
||||||
|
|
||||||
|
if (serverListScreen.selectedServer.TryUnwrap(out var selectedServer) && selectedServer.Equals(info))
|
||||||
|
{
|
||||||
|
serverListScreen.HideServerPreview();
|
||||||
|
}
|
||||||
|
serverListScreen.FilterServers();
|
||||||
|
}, relativeSize: confirmPopupSize, minSize: confirmPopupMinSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ReportReason
|
||||||
|
{
|
||||||
|
Spam,
|
||||||
|
Advertising,
|
||||||
|
Inappropriate
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateReportPrompt(ServerInfo info)
|
||||||
|
{
|
||||||
|
if (!GameAnalyticsManager.SendUserStatistics)
|
||||||
|
{
|
||||||
|
GUI.NotifyPrompt(TextManager.Get("reportserver"), TextManager.Get("reportserverdisabled"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgBox = new GUIMessageBox(
|
||||||
|
headerText: TextManager.Get("reportserver"),
|
||||||
|
text: string.Empty,
|
||||||
|
relativeSize: new Vector2(0.2f, 0.4f),
|
||||||
|
minSize: new Point(380, 430),
|
||||||
|
buttons: Array.Empty<LocalizedString>());
|
||||||
|
|
||||||
|
var layout = new GUILayoutGroup(new RectTransform(Vector2.One, msgBox.Content.RectTransform, Anchor.Center));
|
||||||
|
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform), TextManager.GetWithVariable("reportserverexplanation", "[server]", info.ServerName), wrap: true)
|
||||||
|
{
|
||||||
|
ToolTip = TextManager.Get("reportserverprompttooltip")
|
||||||
|
};
|
||||||
|
|
||||||
|
var listBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform));
|
||||||
|
|
||||||
|
var enums = Enum.GetValues<ReportReason>();
|
||||||
|
foreach (ReportReason reason in enums)
|
||||||
|
{
|
||||||
|
new GUITickBox(new RectTransform(new Vector2(1f, 1f / enums.Length), listBox.Content.RectTransform), TextManager.Get($"reportreason.{reason}"))
|
||||||
|
{
|
||||||
|
UserData = reason
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// padding
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(1f, 0.05f), layout.RectTransform), style: null);
|
||||||
|
|
||||||
|
var buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform))
|
||||||
|
{
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var reportAndHideButton = new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("reportoption.reportandhide"))
|
||||||
|
{
|
||||||
|
Enabled = false,
|
||||||
|
OnClicked = (_, _) =>
|
||||||
|
{
|
||||||
|
CreateFilterServerPrompt(info);
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var reportButton = new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("reportoption.report"))
|
||||||
|
{
|
||||||
|
Enabled = false,
|
||||||
|
OnClicked = (_, _) =>
|
||||||
|
{
|
||||||
|
ReportServer(info, GetUserSelectedReasons());
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("cancel"))
|
||||||
|
{
|
||||||
|
OnClicked = (_, _) =>
|
||||||
|
{
|
||||||
|
msgBox.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var child in listBox.Content.GetAllChildren<GUITickBox>())
|
||||||
|
{
|
||||||
|
child.OnSelected += _ =>
|
||||||
|
{
|
||||||
|
reportAndHideButton.Enabled = reportButton.Enabled = GetUserSelectedReasons().Any();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<ReportReason> GetUserSelectedReasons()
|
||||||
|
=> listBox.Content.Children
|
||||||
|
.Where(static c => c.UserData is ReportReason && c.Selected)
|
||||||
|
.Select(static c => (ReportReason)c.UserData).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReportServer(ServerInfo info, IEnumerable<ReportReason> reasons)
|
||||||
|
{
|
||||||
|
if (!reasons.Any()) { return; }
|
||||||
|
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Info, $"[Spam] Reported server: Name: \"{info.ServerName}\", Message: \"{info.ServerMessage}\", Endpoint: \"{info.Endpoint.StringRepresentation}\". Reason: \"{string.Join(", ", reasons)}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateServerInfoUI(ServerInfo serverInfo)
|
private void UpdateServerInfoUI(ServerInfo serverInfo)
|
||||||
@@ -1571,7 +1734,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
serverFrame.UserData = serverInfo;
|
serverFrame.UserData = serverInfo;
|
||||||
|
|
||||||
serverFrame.ToolTip = "";
|
|
||||||
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
|
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
|
||||||
serverContent.ClearChildren();
|
serverContent.ClearChildren();
|
||||||
|
|
||||||
@@ -1583,15 +1745,14 @@ namespace Barotrauma
|
|||||||
new RectTransform(new Vector2(columns[label].RelativeWidth, 1.0f), serverContent.RectTransform),
|
new RectTransform(new Vector2(columns[label].RelativeWidth, 1.0f), serverContent.RectTransform),
|
||||||
style: null);
|
style: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void errorTooltip(RichString toolTip)
|
void disableElementFocus()
|
||||||
{
|
{
|
||||||
sections.Values.ForEach(c =>
|
sections.Values.ForEach(c =>
|
||||||
{
|
{
|
||||||
c.CanBeFocused = false;
|
c.CanBeFocused = false;
|
||||||
c.Children.First().CanBeFocused = false;
|
c.Children.First().CanBeFocused = false;
|
||||||
});
|
});
|
||||||
serverFrame.ToolTip = toolTip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RectTransform columnRT(ColumnLabel label, float scale = 0.95f)
|
RectTransform columnRT(ColumnLabel label, float scale = 0.95f)
|
||||||
@@ -1611,7 +1772,7 @@ namespace Barotrauma
|
|||||||
NetworkMember.IsCompatible(GameMain.Version, serverInfo.GameVersion),
|
NetworkMember.IsCompatible(GameMain.Version, serverInfo.GameVersion),
|
||||||
UserData = "compatible"
|
UserData = "compatible"
|
||||||
};
|
};
|
||||||
|
|
||||||
var passwordBox = new GUITickBox(columnRT(ColumnLabel.ServerListHasPassword, scale: 0.6f), label: "", style: "GUIServerListPasswordTickBox")
|
var passwordBox = new GUITickBox(columnRT(ColumnLabel.ServerListHasPassword, scale: 0.6f), label: "", style: "GUIServerListPasswordTickBox")
|
||||||
{
|
{
|
||||||
Selected = serverInfo.HasPassword,
|
Selected = serverInfo.HasPassword,
|
||||||
@@ -1664,9 +1825,10 @@ namespace Barotrauma
|
|||||||
serverPingText.TextColor = Color.DarkRed;
|
serverPingText.TextColor = Color.DarkRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalizedString toolTip = "";
|
||||||
if (!serverInfo.Checked)
|
if (!serverInfo.Checked)
|
||||||
{
|
{
|
||||||
errorTooltip(TextManager.Get("ServerOffline"));
|
toolTip = TextManager.Get("ServerOffline");
|
||||||
serverName.TextColor *= 0.8f;
|
serverName.TextColor *= 0.8f;
|
||||||
serverPlayers.TextColor *= 0.8f;
|
serverPlayers.TextColor *= 0.8f;
|
||||||
}
|
}
|
||||||
@@ -1681,7 +1843,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (!compatibleBox.Selected)
|
else if (!compatibleBox.Selected)
|
||||||
{
|
{
|
||||||
LocalizedString toolTip = "";
|
|
||||||
if (serverInfo.GameVersion != GameMain.Version)
|
if (serverInfo.GameVersion != GameMain.Version)
|
||||||
{
|
{
|
||||||
toolTip = TextManager.GetWithVariable("ServerListIncompatibleVersion", "[version]", serverInfo.GameVersion.ToString());
|
toolTip = TextManager.GetWithVariable("ServerListIncompatibleVersion", "[version]", serverInfo.GameVersion.ToString());
|
||||||
@@ -1707,14 +1868,12 @@ namespace Barotrauma
|
|||||||
toolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (incompatibleModNames.Count - maxIncompatibleToList).ToString());
|
toolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (incompatibleModNames.Count - maxIncompatibleToList).ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorTooltip(toolTip);
|
|
||||||
|
|
||||||
serverName.TextColor *= 0.5f;
|
serverName.TextColor *= 0.5f;
|
||||||
serverPlayers.TextColor *= 0.5f;
|
serverPlayers.TextColor *= 0.5f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LocalizedString toolTip = "";
|
|
||||||
foreach (var contentPackage in serverInfo.ContentPackages)
|
foreach (var contentPackage in serverInfo.ContentPackages)
|
||||||
{
|
{
|
||||||
if (ContentPackageManager.EnabledPackages.All.None(cp => cp.Hash.StringRepresentation == contentPackage.Hash))
|
if (ContentPackageManager.EnabledPackages.All.None(cp => cp.Hash.StringRepresentation == contentPackage.Hash))
|
||||||
@@ -1724,8 +1883,11 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorTooltip(toolTip);
|
|
||||||
}
|
}
|
||||||
|
disableElementFocus();
|
||||||
|
|
||||||
|
string separator = toolTip.IsNullOrWhiteSpace() ? "" : "\n\n";
|
||||||
|
serverFrame.ToolTip = RichString.Rich(toolTip + separator + $"‖color:gui.blue‖{TextManager.GetWithVariable("serverlisttooltip", "[button]", PlayerInput.SecondaryMouseLabel)}‖end‖");
|
||||||
|
|
||||||
foreach (var section in sections.Values)
|
foreach (var section in sections.Values)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class SubEditorScreen : EditorScreen
|
class SubEditorScreen : EditorScreen
|
||||||
{
|
{
|
||||||
public const string CircuitBoxDeletionWarningHeader = "Selection contains circuit boxes",
|
|
||||||
CircuitBoxDeletionWarningBody = "Are you sure you want to delete the selection? Any wiring inside circuit boxes will be lost and cannot be recovered.";
|
|
||||||
|
|
||||||
public const int MaxStructures = 2000;
|
public const int MaxStructures = 2000;
|
||||||
public const int MaxWalls = 500;
|
public const int MaxWalls = 500;
|
||||||
public const int MaxItems = 5000;
|
public const int MaxItems = 5000;
|
||||||
@@ -1290,7 +1287,8 @@ namespace Barotrauma
|
|||||||
if (legacy) { textBlock.TextColor *= 0.6f; }
|
if (legacy) { textBlock.TextColor *= 0.6f; }
|
||||||
if (name.IsNullOrEmpty())
|
if (name.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!");
|
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!",
|
||||||
|
contentPackage: ep.ContentPackage);
|
||||||
textBlock.Text = frame.ToolTip = ep.Identifier.Value;
|
textBlock.Text = frame.ToolTip = ep.Identifier.Value;
|
||||||
textBlock.TextColor = GUIStyle.Red;
|
textBlock.TextColor = GUIStyle.Red;
|
||||||
}
|
}
|
||||||
@@ -1562,8 +1560,17 @@ namespace Barotrauma
|
|||||||
if (editorSelectedTime.TryUnwrap(out DateTime selectedTime))
|
if (editorSelectedTime.TryUnwrap(out DateTime selectedTime))
|
||||||
{
|
{
|
||||||
TimeSpan timeInEditor = DateTime.Now - selectedTime;
|
TimeSpan timeInEditor = DateTime.Now - selectedTime;
|
||||||
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
|
if (timeInEditor.TotalSeconds > Timing.TotalTime)
|
||||||
editorSelectedTime = Option<DateTime>.None();
|
{
|
||||||
|
DebugConsole.ThrowErrorAndLogToGA(
|
||||||
|
"SubEditorScreen.DeselectEditorSpecific:InvalidTimeInEditor",
|
||||||
|
$"Error in sub editor screen. Calculated time in editor {timeInEditor} was larger than the time the game has run ({Timing.TotalTime} s).");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
|
||||||
|
editorSelectedTime = Option<DateTime>.None();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2368,49 +2375,58 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//---------------------------------------
|
//---------------------------------------
|
||||||
|
|
||||||
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, subTypeDependentSettingFrame.RectTransform))
|
var extraSettingsContainer = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), subTypeDependentSettingFrame.RectTransform))
|
||||||
{
|
{
|
||||||
CanBeFocused = true,
|
CanBeFocused = true,
|
||||||
Visible = false,
|
Visible = false,
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------
|
var minDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
|
||||||
|
|
||||||
var beaconMinDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
|
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMinDifficultyGroup.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), minDifficultyGroup.RectTransform),
|
||||||
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
||||||
var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
|
var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), minDifficultyGroup.RectTransform), NumberType.Int)
|
||||||
{
|
{
|
||||||
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MinLevelDifficulty ?? 0),
|
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MinLevelDifficulty ?? 0),
|
||||||
MinValueInt = 0,
|
MinValueInt = 0,
|
||||||
MaxValueInt = 100,
|
MaxValueInt = 100,
|
||||||
OnValueChanged = (numberInput) =>
|
OnValueChanged = (numberInput) =>
|
||||||
{
|
{
|
||||||
MainSub.Info.BeaconStationInfo.MinLevelDifficulty = numberInput.IntValue;
|
MainSub.Info.GetExtraSubmarineInfo.MinLevelDifficulty = numberInput.IntValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
beaconMinDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
minDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
||||||
var beaconMaxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
|
var maxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
|
||||||
{
|
{
|
||||||
Stretch = true
|
Stretch = true
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMaxDifficultyGroup.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), maxDifficultyGroup.RectTransform),
|
||||||
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
||||||
numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
|
numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), maxDifficultyGroup.RectTransform), NumberType.Int)
|
||||||
{
|
{
|
||||||
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MaxLevelDifficulty ?? 100),
|
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MaxLevelDifficulty ?? 100),
|
||||||
MinValueInt = 0,
|
MinValueInt = 0,
|
||||||
MaxValueInt = 100,
|
MaxValueInt = 100,
|
||||||
OnValueChanged = (numberInput) =>
|
OnValueChanged = (numberInput) =>
|
||||||
{
|
{
|
||||||
MainSub.Info.BeaconStationInfo.MaxLevelDifficulty = numberInput.IntValue;
|
MainSub.Info.GetExtraSubmarineInfo.MaxLevelDifficulty = numberInput.IntValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
beaconMaxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
maxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------
|
||||||
|
|
||||||
|
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, extraSettingsContainer.RectTransform))
|
||||||
|
{
|
||||||
|
CanBeFocused = true,
|
||||||
|
Visible = false,
|
||||||
|
Stretch = true
|
||||||
|
};
|
||||||
|
|
||||||
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
|
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
|
||||||
{
|
{
|
||||||
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
|
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
|
||||||
@@ -2672,8 +2688,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
|
MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
|
||||||
}
|
}
|
||||||
|
else if (type == SubmarineType.Wreck)
|
||||||
|
{
|
||||||
|
MainSub.Info.WreckInfo ??= new WreckInfo(MainSub.Info);
|
||||||
|
}
|
||||||
previewImageButtonHolder.Children.ForEach(c => c.Enabled = MainSub.Info.AllowPreviewImage);
|
previewImageButtonHolder.Children.ForEach(c => c.Enabled = MainSub.Info.AllowPreviewImage);
|
||||||
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
|
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
|
||||||
|
extraSettingsContainer.Visible = type == SubmarineType.BeaconStation || type == SubmarineType.Wreck;
|
||||||
beaconSettingsContainer.Visible = type == SubmarineType.BeaconStation;
|
beaconSettingsContainer.Visible = type == SubmarineType.BeaconStation;
|
||||||
subSettingsContainer.Visible = type == SubmarineType.Player;
|
subSettingsContainer.Visible = type == SubmarineType.Player;
|
||||||
return true;
|
return true;
|
||||||
@@ -3921,28 +3942,15 @@ namespace Barotrauma
|
|||||||
new ContextMenuOption("editor.cut", isEnabled: hasTargets, onSelected: () => MapEntity.Cut(targets)),
|
new ContextMenuOption("editor.cut", isEnabled: hasTargets, onSelected: () => MapEntity.Cut(targets)),
|
||||||
new ContextMenuOption("editor.copytoclipboard", isEnabled: hasTargets, onSelected: () => MapEntity.Copy(targets)),
|
new ContextMenuOption("editor.copytoclipboard", isEnabled: hasTargets, onSelected: () => MapEntity.Copy(targets)),
|
||||||
new ContextMenuOption("editor.paste", isEnabled: MapEntity.CopiedList.Any(), onSelected: () => MapEntity.Paste(cam.ScreenToWorld(PlayerInput.MousePosition))),
|
new ContextMenuOption("editor.paste", isEnabled: MapEntity.CopiedList.Any(), onSelected: () => MapEntity.Paste(cam.ScreenToWorld(PlayerInput.MousePosition))),
|
||||||
new ContextMenuOption("delete", isEnabled: hasTargets, onSelected: () => RemoveEntitiesWithPossibleWarning(targets)),
|
new ContextMenuOption("delete", isEnabled: hasTargets, onSelected: () =>
|
||||||
new ContextMenuOption(TextManager.Get("editortip.shiftforextraoptions") + '\n' + TextManager.Get("editortip.altforruler"), isEnabled: false, onSelected: null));
|
{
|
||||||
}
|
StoreCommand(new AddOrDeleteCommand(targets, true));
|
||||||
}
|
foreach (var me in targets)
|
||||||
|
{
|
||||||
public static void RemoveEntitiesWithPossibleWarning(List<MapEntity> targets)
|
if (!me.Removed) { me.Remove(); }
|
||||||
{
|
}
|
||||||
if (targets.Any(static t => t is Item it && it.GetComponent<CircuitBox>() is not null))
|
}),
|
||||||
{
|
new ContextMenuOption(TextManager.GetWithVariable("editortip.shiftforextraoptions", "[button]", PlayerInput.SecondaryMouseLabel) + '\n' + TextManager.Get("editortip.altforruler"), isEnabled: false, onSelected: null));
|
||||||
GUI.AskForConfirmation(CircuitBoxDeletionWarningHeader, CircuitBoxDeletionWarningBody, onConfirm: Delete);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Delete();
|
|
||||||
|
|
||||||
void Delete()
|
|
||||||
{
|
|
||||||
StoreCommand(new AddOrDeleteCommand(targets, true));
|
|
||||||
foreach (var me in targets)
|
|
||||||
{
|
|
||||||
if (!me.Removed) { me.Remove(); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4442,6 +4450,7 @@ namespace Barotrauma
|
|||||||
MapEntity.SelectEntity(itemContainer);
|
MapEntity.SelectEntity(itemContainer);
|
||||||
dummyCharacter.SelectedItem = itemContainer;
|
dummyCharacter.SelectedItem = itemContainer;
|
||||||
FilterEntities(entityFilterBox.Text);
|
FilterEntities(entityFilterBox.Text);
|
||||||
|
MapEntity.StopSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -5472,9 +5481,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (LightComponent lightComponent in item.GetComponents<LightComponent>())
|
foreach (LightComponent lightComponent in item.GetComponents<LightComponent>())
|
||||||
{
|
{
|
||||||
lightComponent.Light.Color = item.Container != null || (item.body != null && !item.body.Enabled) ?
|
lightComponent.Light.Color =
|
||||||
Color.Transparent :
|
item.body == null || item.body.Enabled ||
|
||||||
lightComponent.LightColor;
|
(item.ParentInventory is ItemInventory itemInventory && !itemInventory.Container.HideItems) ?
|
||||||
|
lightComponent.LightColor :
|
||||||
|
Color.Transparent;
|
||||||
lightComponent.Light.LightSpriteEffect = lightComponent.Item.SpriteEffects;
|
lightComponent.Light.LightSpriteEffect = lightComponent.Item.SpriteEffects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5559,11 +5570,32 @@ namespace Barotrauma
|
|||||||
dummyCharacter.Submarine = MainSub;
|
dummyCharacter.Submarine = MainSub;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deposit item from our "infinite stack" into inventory slots
|
if (dummyCharacter?.SelectedItem != null)
|
||||||
var inv = dummyCharacter?.SelectedItem?.OwnInventory;
|
|
||||||
if (inv?.visualSlots != null && !PlayerInput.IsCtrlDown())
|
|
||||||
{
|
{
|
||||||
var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
|
// Deposit item from our "infinite stack" into inventory slots
|
||||||
|
TryDragItemsToItem(dummyCharacter.SelectedItem);
|
||||||
|
foreach (Item linkedItem in dummyCharacter.SelectedItem.linkedTo.OfType<Item>())
|
||||||
|
{
|
||||||
|
TryDragItemsToItem(linkedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryDragItemsToItem(Item item)
|
||||||
|
{
|
||||||
|
foreach (ItemContainer ic in item.GetComponents<ItemContainer>())
|
||||||
|
{
|
||||||
|
if (ic.Inventory?.visualSlots != null)
|
||||||
|
{
|
||||||
|
TryDragItemsToInventory(ic.Inventory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryDragItemsToInventory(Inventory inv)
|
||||||
|
{
|
||||||
|
if (PlayerInput.IsCtrlDown()) { return; }
|
||||||
|
|
||||||
|
var draggingMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
|
||||||
|
|
||||||
// So we don't accidentally drag inventory items while doing this
|
// So we don't accidentally drag inventory items while doing this
|
||||||
if (DraggedItemPrefab != null) { Inventory.DraggingItems.Clear(); }
|
if (DraggedItemPrefab != null) { Inventory.DraggingItems.Clear(); }
|
||||||
@@ -5571,134 +5603,134 @@ namespace Barotrauma
|
|||||||
switch (DraggedItemPrefab)
|
switch (DraggedItemPrefab)
|
||||||
{
|
{
|
||||||
// regular item prefabs
|
// regular item prefabs
|
||||||
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || dragginMouse:
|
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || draggingMouse:
|
||||||
{
|
|
||||||
bool spawnedItem = false;
|
|
||||||
for (var i = 0; i < inv.Capacity; i++)
|
|
||||||
{
|
{
|
||||||
var slot = inv.visualSlots[i];
|
bool spawnedItem = false;
|
||||||
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
|
for (var i = 0; i < inv.Capacity; i++)
|
||||||
|
|
||||||
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
|
|
||||||
if (Inventory.IsMouseOnSlot(slot))
|
|
||||||
{
|
{
|
||||||
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
|
var slot = inv.visualSlots[i];
|
||||||
|
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
|
||||||
|
|
||||||
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
|
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
|
||||||
|
if (Inventory.IsMouseOnSlot(slot))
|
||||||
{
|
{
|
||||||
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
|
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
|
||||||
spawnedItem |= placedItem;
|
|
||||||
|
|
||||||
if (!placedItem)
|
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
|
||||||
{
|
{
|
||||||
newItem.Remove();
|
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
|
||||||
|
spawnedItem |= placedItem;
|
||||||
|
|
||||||
|
if (!placedItem)
|
||||||
|
{
|
||||||
|
newItem.Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
|
||||||
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
|
|
||||||
{
|
|
||||||
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
|
|
||||||
spawnedItem |= placedItem;
|
|
||||||
|
|
||||||
// try to place the item into the inventory of the item we are hovering over
|
|
||||||
if (!placedItem)
|
|
||||||
{
|
{
|
||||||
newItem.Remove();
|
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
|
||||||
|
spawnedItem |= placedItem;
|
||||||
|
|
||||||
|
// try to place the item into the inventory of the item we are hovering over
|
||||||
|
if (!placedItem)
|
||||||
|
{
|
||||||
|
newItem.Remove();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
|
newItem.Remove();
|
||||||
|
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newItem.Removed)
|
||||||
|
{
|
||||||
|
BulkItemBufferInUse = ItemAddMutex;
|
||||||
|
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!draggingMouse)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
newItem.Remove();
|
|
||||||
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newItem.Removed)
|
|
||||||
{
|
|
||||||
BulkItemBufferInUse = ItemAddMutex;
|
|
||||||
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dragginMouse)
|
|
||||||
{
|
|
||||||
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
// item assemblies
|
// item assemblies
|
||||||
case ItemAssemblyPrefab assemblyPrefab when PlayerInput.PrimaryMouseButtonClicked():
|
case ItemAssemblyPrefab assemblyPrefab when PlayerInput.PrimaryMouseButtonClicked():
|
||||||
{
|
|
||||||
bool spawnedItems = false;
|
|
||||||
for (var i = 0; i < inv.visualSlots.Length; i++)
|
|
||||||
{
|
{
|
||||||
var slot = inv.visualSlots[i];
|
bool spawnedItems = false;
|
||||||
var item = inv?.GetItemAt(i);
|
for (var i = 0; i < inv.visualSlots.Length; i++)
|
||||||
var itemContainer = item?.GetComponent<ItemContainer>();
|
|
||||||
if (item == null && Inventory.IsMouseOnSlot(slot))
|
|
||||||
{
|
{
|
||||||
// load the items
|
var slot = inv.visualSlots[i];
|
||||||
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
|
var item = inv?.GetItemAt(i);
|
||||||
|
var itemContainer = item?.GetComponent<ItemContainer>();
|
||||||
// counter for items that failed so we so we known that slot remained empty
|
if (item == null && Inventory.IsMouseOnSlot(slot))
|
||||||
var failedCount = 0;
|
|
||||||
|
|
||||||
for (var j = 0; j < itemInstance.Count(); j++)
|
|
||||||
{
|
{
|
||||||
var newItem = itemInstance[j];
|
// load the items
|
||||||
var newSpot = i + j - failedCount;
|
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
|
||||||
|
|
||||||
// try to find a valid slot to put the items
|
// counter for items that failed so we so we known that slot remained empty
|
||||||
while (inv.visualSlots.Length > newSpot)
|
var failedCount = 0;
|
||||||
|
|
||||||
|
for (var j = 0; j < itemInstance.Count; j++)
|
||||||
{
|
{
|
||||||
if (inv.GetItemAt(newSpot) == null) { break; }
|
var newItem = itemInstance[j];
|
||||||
newSpot++;
|
var newSpot = i + j - failedCount;
|
||||||
}
|
|
||||||
|
|
||||||
// valid slot found
|
// try to find a valid slot to put the items
|
||||||
if (inv.visualSlots.Length > newSpot)
|
while (inv.visualSlots.Length > newSpot)
|
||||||
{
|
|
||||||
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
|
|
||||||
spawnedItems |= placedItem;
|
|
||||||
|
|
||||||
if (!placedItem)
|
|
||||||
{
|
{
|
||||||
failedCount++;
|
if (inv.GetItemAt(newSpot) == null) { break; }
|
||||||
// delete the included items too so we don't get a popup asking if we want to keep them
|
newSpot++;
|
||||||
newItem?.OwnInventory?.DeleteAllItems();
|
}
|
||||||
newItem.Remove();
|
|
||||||
|
// valid slot found
|
||||||
|
if (inv.visualSlots.Length > newSpot)
|
||||||
|
{
|
||||||
|
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
|
||||||
|
spawnedItems |= placedItem;
|
||||||
|
|
||||||
|
if (!placedItem)
|
||||||
|
{
|
||||||
|
failedCount++;
|
||||||
|
// delete the included items too so we don't get a popup asking if we want to keep them
|
||||||
|
newItem?.OwnInventory?.DeleteAllItems();
|
||||||
|
newItem.Remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
|
||||||
|
spawnedItems |= placedItem;
|
||||||
|
|
||||||
|
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
|
||||||
|
if (!placedItem)
|
||||||
|
{
|
||||||
|
// delete the included items too so we don't get a popup asking if we want to keep them
|
||||||
|
newItem?.OwnInventory?.DeleteAllItems();
|
||||||
|
newItem.Remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
||||||
|
if (placedEntities.Any())
|
||||||
{
|
{
|
||||||
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
|
BulkItemBufferInUse = ItemAddMutex;
|
||||||
spawnedItems |= placedItem;
|
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
|
||||||
|
|
||||||
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
|
|
||||||
if (!placedItem)
|
|
||||||
{
|
|
||||||
// delete the included items too so we don't get a popup asking if we want to keep them
|
|
||||||
newItem?.OwnInventory?.DeleteAllItems();
|
|
||||||
newItem.Remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
|
|
||||||
if (placedEntities.Any())
|
|
||||||
{
|
|
||||||
BulkItemBufferInUse = ItemAddMutex;
|
|
||||||
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -571,16 +571,37 @@ namespace Barotrauma
|
|||||||
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
||||||
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
||||||
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
||||||
numberInput.valueStep = editableAttribute.ValueStep;
|
numberInput.ValueStep = editableAttribute.ValueStep;
|
||||||
|
numberInput.ForceShowPlusMinusButtons = editableAttribute.ForceShowPlusMinusButtons;
|
||||||
numberInput.FloatValue = value;
|
numberInput.FloatValue = value;
|
||||||
|
|
||||||
numberInput.OnValueChanged += (numInput) =>
|
numberInput.OnValueChanged += numInput =>
|
||||||
{
|
{
|
||||||
if (SetPropertyValue(property, entity, numInput.FloatValue))
|
if (SetPropertyValue(property, entity, numInput.FloatValue))
|
||||||
{
|
{
|
||||||
TrySendNetworkUpdate(entity, property);
|
TrySendNetworkUpdate(entity, property);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Lots of UI boilerplate to handle all(?) cases where the property's setter may be called
|
||||||
|
// and modify the input value (e.g. rotation value wrapping)
|
||||||
|
void HandleSetterModifyingInput(GUINumberInput numInput)
|
||||||
|
{
|
||||||
|
var inputFloatValue = numInput.FloatValue;
|
||||||
|
var resultingFloatValue = property.GetFloatValue(entity);
|
||||||
|
if (!MathUtils.NearlyEqual(resultingFloatValue, inputFloatValue))
|
||||||
|
{
|
||||||
|
numInput.FloatValue = resultingFloatValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool HandleSetterModifyingInputOnButtonPressed() { HandleSetterModifyingInput(numberInput); return true; }
|
||||||
|
bool HandleSetterModifyingInputOnButtonClicked(GUIButton _, object __) { HandleSetterModifyingInput(numberInput); return true; }
|
||||||
|
|
||||||
|
numberInput.OnValueEntered += HandleSetterModifyingInput;
|
||||||
|
numberInput.PlusButton.OnPressed += HandleSetterModifyingInputOnButtonPressed;
|
||||||
|
numberInput.PlusButton.OnClicked += HandleSetterModifyingInputOnButtonClicked;
|
||||||
|
numberInput.MinusButton.OnPressed += HandleSetterModifyingInputOnButtonPressed;
|
||||||
|
numberInput.MinusButton.OnClicked += HandleSetterModifyingInputOnButtonClicked;
|
||||||
refresh += () =>
|
refresh += () =>
|
||||||
{
|
{
|
||||||
if (!numberInput.TextBox.Selected) { numberInput.FloatValue = (float)property.GetValue(entity); }
|
if (!numberInput.TextBox.Selected) { numberInput.FloatValue = (float)property.GetValue(entity); }
|
||||||
@@ -859,7 +880,7 @@ namespace Barotrauma
|
|||||||
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
||||||
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
||||||
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
||||||
numberInput.valueStep = editableAttribute.ValueStep;
|
numberInput.ValueStep = editableAttribute.ValueStep;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
numberInput.FloatValue = value.X;
|
numberInput.FloatValue = value.X;
|
||||||
@@ -930,7 +951,7 @@ namespace Barotrauma
|
|||||||
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
||||||
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
||||||
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
||||||
numberInput.valueStep = editableAttribute.ValueStep;
|
numberInput.ValueStep = editableAttribute.ValueStep;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
numberInput.FloatValue = value.X;
|
numberInput.FloatValue = value.X;
|
||||||
@@ -1006,7 +1027,7 @@ namespace Barotrauma
|
|||||||
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
|
||||||
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
|
||||||
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
|
||||||
numberInput.valueStep = editableAttribute.ValueStep;
|
numberInput.ValueStep = editableAttribute.ValueStep;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
numberInput.FloatValue = value.X;
|
numberInput.FloatValue = value.X;
|
||||||
|
|||||||
@@ -727,7 +727,21 @@ namespace Barotrauma
|
|||||||
Slider(layout, (0.75f, 1.25f), 51, Percentage, unsavedConfig.Graphics.InventoryScale, v => unsavedConfig.Graphics.InventoryScale = v);
|
Slider(layout, (0.75f, 1.25f), 51, Percentage, unsavedConfig.Graphics.InventoryScale, v => unsavedConfig.Graphics.InventoryScale = v);
|
||||||
Label(layout, TextManager.Get("TextScale"), GUIStyle.SubHeadingFont);
|
Label(layout, TextManager.Get("TextScale"), GUIStyle.SubHeadingFont);
|
||||||
Slider(layout, (0.75f, 1.25f), 51, Percentage, unsavedConfig.Graphics.TextScale, v => unsavedConfig.Graphics.TextScale = v);
|
Slider(layout, (0.75f, 1.25f), 51, Percentage, unsavedConfig.Graphics.TextScale, v => unsavedConfig.Graphics.TextScale = v);
|
||||||
|
Spacer(layout);
|
||||||
|
var resetSpamListFilter =
|
||||||
|
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), layout.RectTransform),
|
||||||
|
TextManager.Get("clearserverlistfilters"), style: "GUIButtonSmall")
|
||||||
|
{
|
||||||
|
OnClicked = static (_, _) =>
|
||||||
|
{
|
||||||
|
GUI.AskForConfirmation(
|
||||||
|
header: TextManager.Get("clearserverlistfilters"),
|
||||||
|
body: TextManager.Get("clearserverlistfiltersconfirmation"),
|
||||||
|
onConfirm: SpamServerFilters.ClearLocalSpamFilter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Spacer(layout);
|
||||||
#if !OSX
|
#if !OSX
|
||||||
Spacer(layout);
|
Spacer(layout);
|
||||||
var statisticsTickBox = new GUITickBox(NewItemRectT(layout), TextManager.Get("statisticsconsenttickbox"))
|
var statisticsTickBox = new GUITickBox(NewItemRectT(layout), TextManager.Get("statisticsconsenttickbox"))
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
using System;
|
using NVorbis;
|
||||||
using OpenAL;
|
using OpenAL;
|
||||||
using NVorbis;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma.Sounds
|
namespace Barotrauma.Sounds
|
||||||
{
|
{
|
||||||
sealed class OggSound : Sound
|
sealed class OggSound : Sound
|
||||||
{
|
{
|
||||||
private VorbisReader streamReader;
|
private readonly VorbisReader streamReader;
|
||||||
|
|
||||||
|
public long MaxStreamSamplePos => streamReader == null ? 0 : streamReader.TotalSamples * streamReader.Channels * 2;
|
||||||
|
|
||||||
private List<float> playbackAmplitude;
|
private List<float> playbackAmplitude;
|
||||||
private const int AMPLITUDE_SAMPLE_COUNT = 4410; //100ms in a 44100hz file
|
private const int AMPLITUDE_SAMPLE_COUNT = 4410; //100ms in a 44100hz file
|
||||||
|
|
||||||
private short[] sampleBuffer = Array.Empty<short>();
|
private short[] sampleBuffer = Array.Empty<short>();
|
||||||
private short[] muffleBuffer = Array.Empty<short>();
|
private short[] muffleBuffer = Array.Empty<short>();
|
||||||
public OggSound(SoundManager owner, string filename, bool stream, XElement xElement) : base(owner, filename,
|
public OggSound(SoundManager owner, string filename, bool stream, ContentXElement xElement) : base(owner, filename,
|
||||||
stream, true, xElement)
|
stream, true, xElement)
|
||||||
{
|
{
|
||||||
var reader = new VorbisReader(Filename);
|
var reader = new VorbisReader(Filename);
|
||||||
@@ -101,7 +102,7 @@ namespace Barotrauma.Sounds
|
|||||||
if (!Stream) { throw new Exception("Called FillStreamBuffer on a non-streamed sound!"); }
|
if (!Stream) { throw new Exception("Called FillStreamBuffer on a non-streamed sound!"); }
|
||||||
if (streamReader == null) { throw new Exception("Called FillStreamBuffer when the reader is null!"); }
|
if (streamReader == null) { throw new Exception("Called FillStreamBuffer when the reader is null!"); }
|
||||||
|
|
||||||
if (samplePos >= streamReader.TotalSamples * streamReader.Channels * 2) return 0;
|
if (samplePos >= MaxStreamSamplePos) { return 0; }
|
||||||
|
|
||||||
samplePos /= streamReader.Channels * 2;
|
samplePos /= streamReader.Channels * 2;
|
||||||
streamReader.DecodedPosition = samplePos;
|
streamReader.DecodedPosition = samplePos;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
public readonly string Filename;
|
public readonly string Filename;
|
||||||
|
|
||||||
public readonly XElement XElement;
|
public readonly ContentXElement XElement;
|
||||||
|
|
||||||
public readonly bool Stream;
|
public readonly bool Stream;
|
||||||
|
|
||||||
@@ -60,14 +60,14 @@ namespace Barotrauma.Sounds
|
|||||||
public float BaseNear;
|
public float BaseNear;
|
||||||
public float BaseFar;
|
public float BaseFar;
|
||||||
|
|
||||||
public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, XElement xElement = null, bool getFullPath = true)
|
public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, ContentXElement xElement = null, bool getFullPath = true)
|
||||||
{
|
{
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
Filename = getFullPath ? Path.GetFullPath(filename.CleanUpPath()).CleanUpPath() : filename;
|
Filename = getFullPath ? Path.GetFullPath(filename.CleanUpPath()).CleanUpPath() : filename;
|
||||||
Stream = stream;
|
Stream = stream;
|
||||||
StreamsReliably = streamsReliably;
|
StreamsReliably = streamsReliably;
|
||||||
XElement = xElement;
|
XElement = xElement;
|
||||||
sourcePoolIndex = XElement.GetAttributeEnum("sourcepool", SoundManager.SourcePoolIndex.Default);
|
sourcePoolIndex = XElement?.GetAttributeEnum("sourcepool", SoundManager.SourcePoolIndex.Default) ?? SoundManager.SourcePoolIndex.Default;
|
||||||
|
|
||||||
BaseGain = 1.0f;
|
BaseGain = 1.0f;
|
||||||
BaseNear = 100.0f;
|
BaseNear = 100.0f;
|
||||||
|
|||||||
@@ -444,6 +444,18 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long MaxStreamSeekPos
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsStream || Sound is not OggSound oggSound)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return oggSound.MaxStreamSamplePos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly object mutex;
|
private readonly object mutex;
|
||||||
|
|
||||||
public bool IsPlaying
|
public bool IsPlaying
|
||||||
@@ -564,7 +576,7 @@ namespace Barotrauma.Sounds
|
|||||||
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid! " + debugName);
|
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid! " + debugName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sound.Owner.InitStreamThread();
|
Sound.Owner.InitUpdateChannelThread();
|
||||||
SetProperties();
|
SetProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -609,6 +621,7 @@ namespace Barotrauma.Sounds
|
|||||||
public void FadeOutAndDispose()
|
public void FadeOutAndDispose()
|
||||||
{
|
{
|
||||||
FadingOutAndDisposing = true;
|
FadingOutAndDisposing = true;
|
||||||
|
Sound.Owner.InitUpdateChannelThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Barotrauma.Sounds
|
|||||||
|
|
||||||
public bool Disconnected { get; private set; }
|
public bool Disconnected { get; private set; }
|
||||||
|
|
||||||
private Thread streamingThread;
|
private Thread updateChannelsThread;
|
||||||
|
|
||||||
private Vector3 listenerPosition;
|
private Vector3 listenerPosition;
|
||||||
public Vector3 ListenerPosition
|
public Vector3 ListenerPosition
|
||||||
@@ -201,7 +201,7 @@ namespace Barotrauma.Sounds
|
|||||||
public SoundManager()
|
public SoundManager()
|
||||||
{
|
{
|
||||||
loadedSounds = new List<Sound>();
|
loadedSounds = new List<Sound>();
|
||||||
streamingThread = null;
|
updateChannelsThread = null;
|
||||||
|
|
||||||
sourcePools = new SoundSourcePool[2];
|
sourcePools = new SoundSourcePool[2];
|
||||||
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
||||||
@@ -696,7 +696,7 @@ namespace Barotrauma.Sounds
|
|||||||
CompressionDynamicRangeGain = 1.0f;
|
CompressionDynamicRangeGain = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streamingThread == null || streamingThread.ThreadState.HasFlag(ThreadState.Stopped))
|
if (updateChannelsThread == null || updateChannelsThread.ThreadState.HasFlag(ThreadState.Stopped))
|
||||||
{
|
{
|
||||||
bool startedStreamThread = false;
|
bool startedStreamThread = false;
|
||||||
for (int i = 0; i < playingChannels.Length; i++)
|
for (int i = 0; i < playingChannels.Length; i++)
|
||||||
@@ -708,7 +708,7 @@ namespace Barotrauma.Sounds
|
|||||||
if (playingChannels[i][j] == null) { continue; }
|
if (playingChannels[i][j] == null) { continue; }
|
||||||
if (playingChannels[i][j].IsStream && playingChannels[i][j].IsPlaying)
|
if (playingChannels[i][j].IsStream && playingChannels[i][j].IsPlaying)
|
||||||
{
|
{
|
||||||
InitStreamThread();
|
InitUpdateChannelThread();
|
||||||
startedStreamThread = true;
|
startedStreamThread = true;
|
||||||
}
|
}
|
||||||
if (startedStreamThread) { break; }
|
if (startedStreamThread) { break; }
|
||||||
@@ -727,37 +727,43 @@ namespace Barotrauma.Sounds
|
|||||||
SetCategoryGainMultiplier("music", GameSettings.CurrentConfig.Audio.MusicVolume, 0);
|
SetCategoryGainMultiplier("music", GameSettings.CurrentConfig.Audio.MusicVolume, 0);
|
||||||
SetCategoryGainMultiplier("voip", Math.Min(GameSettings.CurrentConfig.Audio.VoiceChatVolume, 1.0f), 0);
|
SetCategoryGainMultiplier("voip", Math.Min(GameSettings.CurrentConfig.Audio.VoiceChatVolume, 1.0f), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitStreamThread()
|
/// <summary>
|
||||||
|
/// Initializes the thread that handles streaming audio and fading out and disposing channels that are no longer needed.
|
||||||
|
/// </summary>
|
||||||
|
public void InitUpdateChannelThread()
|
||||||
{
|
{
|
||||||
if (Disabled) { return; }
|
if (Disabled) { return; }
|
||||||
bool isStreamThreadDying;
|
bool isUpdateChannelsThreadDying;
|
||||||
lock (threadDeathMutex)
|
lock (threadDeathMutex)
|
||||||
{
|
{
|
||||||
isStreamThreadDying = !areStreamsPlaying;
|
isUpdateChannelsThreadDying = !needsUpdateChannels;
|
||||||
}
|
}
|
||||||
if (streamingThread == null || streamingThread.ThreadState.HasFlag(ThreadState.Stopped) || isStreamThreadDying)
|
if (updateChannelsThread == null || updateChannelsThread.ThreadState.HasFlag(ThreadState.Stopped) || isUpdateChannelsThreadDying)
|
||||||
{
|
{
|
||||||
if (streamingThread != null && !streamingThread.Join(1000))
|
if (updateChannelsThread != null && !updateChannelsThread.Join(1000))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Sound stream thread join timed out!");
|
DebugConsole.ThrowError("SoundManager.UpdateChannels thread join timed out!");
|
||||||
}
|
}
|
||||||
areStreamsPlaying = true;
|
needsUpdateChannels = true;
|
||||||
streamingThread = new Thread(UpdateStreaming)
|
updateChannelsThread = new Thread(UpdateChannels)
|
||||||
{
|
{
|
||||||
Name = "SoundManager Streaming Thread",
|
Name = "SoundManager.UpdateChannels Thread",
|
||||||
IsBackground = true //this should kill the thread if the game crashes
|
IsBackground = true //this should kill the thread if the game crashes
|
||||||
};
|
};
|
||||||
streamingThread.Start();
|
updateChannelsThread.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool areStreamsPlaying = false;
|
private bool needsUpdateChannels = false;
|
||||||
ManualResetEvent streamMre = null;
|
private ManualResetEvent updateChannelsMre = null;
|
||||||
|
|
||||||
void UpdateStreaming()
|
/// <summary>
|
||||||
|
/// Handles streaming audio and fading out and disposing channels that are no longer needed.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateChannels()
|
||||||
{
|
{
|
||||||
streamMre = new ManualResetEvent(false);
|
updateChannelsMre = new ManualResetEvent(false);
|
||||||
bool killThread = false;
|
bool killThread = false;
|
||||||
while (!killThread)
|
while (!killThread)
|
||||||
{
|
{
|
||||||
@@ -784,6 +790,7 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
else if (playingChannels[i][j].FadingOutAndDisposing)
|
else if (playingChannels[i][j].FadingOutAndDisposing)
|
||||||
{
|
{
|
||||||
|
killThread = false;
|
||||||
playingChannels[i][j].Gain -= 0.1f;
|
playingChannels[i][j].Gain -= 0.1f;
|
||||||
if (playingChannels[i][j].Gain <= 0.0f)
|
if (playingChannels[i][j].Gain <= 0.0f)
|
||||||
{
|
{
|
||||||
@@ -794,18 +801,18 @@ namespace Barotrauma.Sounds
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
streamMre.WaitOne(10);
|
updateChannelsMre.WaitOne(10);
|
||||||
streamMre.Reset();
|
updateChannelsMre.Reset();
|
||||||
lock (threadDeathMutex)
|
lock (threadDeathMutex)
|
||||||
{
|
{
|
||||||
areStreamsPlaying = !killThread;
|
needsUpdateChannels = !killThread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ForceStreamUpdate()
|
public void ForceStreamUpdate()
|
||||||
{
|
{
|
||||||
streamMre?.Set();
|
updateChannelsMre?.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReloadSounds()
|
private void ReloadSounds()
|
||||||
@@ -824,12 +831,12 @@ namespace Barotrauma.Sounds
|
|||||||
{
|
{
|
||||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||||
{
|
{
|
||||||
if (playingChannels[i][j] != null) playingChannels[i][j].Dispose();
|
playingChannels[i][j]?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
streamingThread?.Join();
|
updateChannelsThread?.Join();
|
||||||
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (keepSounds)
|
if (keepSounds)
|
||||||
|
|||||||
@@ -709,6 +709,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
musicChannel[i].StreamSeekPos = targetMusic[i].PreviousTime;
|
musicChannel[i].StreamSeekPos = targetMusic[i].PreviousTime;
|
||||||
}
|
}
|
||||||
|
else if (targetMusic[i].StartFromRandomTime)
|
||||||
|
{
|
||||||
|
musicChannel[i].StreamSeekPos =
|
||||||
|
(int)(musicChannel[i].MaxStreamSeekPos * Rand.Range(0.0f, 1.0f, Rand.RandSync.Unsynced));
|
||||||
|
}
|
||||||
musicChannel[i].Looping = true;
|
musicChannel[i].Looping = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ namespace Barotrauma
|
|||||||
public readonly bool MuteIntensityTracks;
|
public readonly bool MuteIntensityTracks;
|
||||||
public readonly float? ForceIntensityTrack;
|
public readonly float? ForceIntensityTrack;
|
||||||
|
|
||||||
|
public readonly bool StartFromRandomTime;
|
||||||
public readonly bool ContinueFromPreviousTime;
|
public readonly bool ContinueFromPreviousTime;
|
||||||
public int PreviousTime;
|
public int PreviousTime;
|
||||||
|
|
||||||
@@ -255,6 +256,7 @@ namespace Barotrauma
|
|||||||
ForceIntensityTrack = element.GetAttributeFloat(nameof(ForceIntensityTrack), 0.0f);
|
ForceIntensityTrack = element.GetAttributeFloat(nameof(ForceIntensityTrack), 0.0f);
|
||||||
}
|
}
|
||||||
Volume = element.GetAttributeFloat(nameof(Volume), 1.0f);
|
Volume = element.GetAttributeFloat(nameof(Volume), 1.0f);
|
||||||
|
StartFromRandomTime = element.GetAttributeBool(nameof(StartFromRandomTime), false);
|
||||||
ContinueFromPreviousTime = element.GetAttributeBool(nameof(ContinueFromPreviousTime), false);
|
ContinueFromPreviousTime = element.GetAttributeBool(nameof(ContinueFromPreviousTime), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,330 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Cache;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.IO;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
using RestSharp;
|
||||||
|
using XmlWriter = Barotrauma.IO.XmlWriter;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
public enum SpamServerFilterType
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
NameEquals,
|
||||||
|
NameContains,
|
||||||
|
MessageEquals,
|
||||||
|
MessageContains,
|
||||||
|
PlayerCountLarger,
|
||||||
|
PlayerCountExact,
|
||||||
|
MaxPlayersLarger,
|
||||||
|
MaxPlayersExact,
|
||||||
|
GameModeEquals,
|
||||||
|
PlayStyleEquals,
|
||||||
|
Endpoint,
|
||||||
|
LanguageEquals
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly record struct SpamFilter(ImmutableHashSet<(SpamServerFilterType Type, string Value)> Filters)
|
||||||
|
{
|
||||||
|
public bool IsFiltered(ServerInfo info)
|
||||||
|
{
|
||||||
|
if (!Filters.Any()) { return false; }
|
||||||
|
|
||||||
|
foreach (var (type, value) in Filters)
|
||||||
|
{
|
||||||
|
if (!IsFiltered(info, type, value)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFiltered(ServerInfo info, SpamServerFilterType type, string value)
|
||||||
|
{
|
||||||
|
string desc = info.ServerMessage,
|
||||||
|
name = info.ServerName;
|
||||||
|
|
||||||
|
int.TryParse(value, out int parsedInt);
|
||||||
|
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
SpamServerFilterType.NameEquals => CompareEquals(name, value),
|
||||||
|
SpamServerFilterType.NameContains => CompareContains(name, value),
|
||||||
|
|
||||||
|
SpamServerFilterType.MessageEquals => CompareEquals(desc, value),
|
||||||
|
SpamServerFilterType.MessageContains => CompareContains(desc, value),
|
||||||
|
|
||||||
|
SpamServerFilterType.Endpoint => info.Endpoint.StringRepresentation.Equals(value, StringComparison.OrdinalIgnoreCase),
|
||||||
|
|
||||||
|
SpamServerFilterType.PlayerCountLarger => info.PlayerCount > parsedInt,
|
||||||
|
SpamServerFilterType.PlayerCountExact => info.PlayerCount == parsedInt,
|
||||||
|
|
||||||
|
SpamServerFilterType.MaxPlayersLarger => info.MaxPlayers > parsedInt,
|
||||||
|
SpamServerFilterType.MaxPlayersExact => info.MaxPlayers == parsedInt,
|
||||||
|
|
||||||
|
SpamServerFilterType.GameModeEquals => info.GameMode == value,
|
||||||
|
SpamServerFilterType.PlayStyleEquals => info.PlayStyle.ToIdentifier() == value,
|
||||||
|
|
||||||
|
SpamServerFilterType.LanguageEquals => info.Language.Value == value,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool CompareEquals(string a, string b)
|
||||||
|
=> a.Equals(b, StringComparison.OrdinalIgnoreCase) || Homoglyphs.Compare(a, b);
|
||||||
|
|
||||||
|
static bool CompareContains(string a, string b)
|
||||||
|
=> a.Contains(b, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XElement Serialize()
|
||||||
|
{
|
||||||
|
var element = new XElement("Filter");
|
||||||
|
|
||||||
|
foreach (var (type, value) in Filters)
|
||||||
|
{
|
||||||
|
element.Add(new XAttribute(type.ToString().ToLowerInvariant(), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(XElement element, out SpamFilter filter)
|
||||||
|
{
|
||||||
|
var builder = ImmutableHashSet.CreateBuilder<(SpamServerFilterType Type, string Value)>();
|
||||||
|
foreach (var attribute in element.Attributes())
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse(attribute.Name.ToString(), ignoreCase: true, out SpamServerFilterType e))
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Failed to parse spam filter attribute \"{attribute.Name}\"");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (e is SpamServerFilterType.Invalid) { continue; }
|
||||||
|
builder.Add((e, attribute.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder.Any())
|
||||||
|
{
|
||||||
|
filter = new SpamFilter(builder.ToImmutable());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return !Filters.Any() ? "Invalid Filter" : string.Join(", ", Filters.Select(static f => $"{f.Type}: {f.Value}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class SpamServerFilter
|
||||||
|
{
|
||||||
|
public readonly ImmutableArray<SpamFilter> Filters;
|
||||||
|
|
||||||
|
public bool IsFiltered(ServerInfo info)
|
||||||
|
{
|
||||||
|
foreach (var f in Filters)
|
||||||
|
{
|
||||||
|
if (f.IsFiltered(info)) { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpamServerFilter(XElement element)
|
||||||
|
{
|
||||||
|
var builder = ImmutableArray.CreateBuilder<SpamFilter>();
|
||||||
|
foreach (var subElement in element.Elements())
|
||||||
|
{
|
||||||
|
if (SpamFilter.TryParse(subElement, out var filter))
|
||||||
|
{
|
||||||
|
builder.Add(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Filters = builder.ToImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpamServerFilter(ImmutableArray<SpamFilter> filters)
|
||||||
|
=> Filters = filters;
|
||||||
|
|
||||||
|
public readonly static string SavePath = Path.Combine("Data", "serverblacklist.xml");
|
||||||
|
|
||||||
|
public void Save(string path)
|
||||||
|
{
|
||||||
|
var comment = new XComment(SpamServerFilters.LocalFilterComment);
|
||||||
|
var doc = new XDocument(comment, new XElement("Filters"));
|
||||||
|
foreach (var filter in Filters)
|
||||||
|
{
|
||||||
|
doc.Root?.Add(filter.Serialize());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var writer = XmlWriter.Create(path, new XmlWriterSettings { Indent = true });
|
||||||
|
doc.SaveSafe(writer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Saving spam filter failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class SpamServerFilters
|
||||||
|
{
|
||||||
|
public static Option<SpamServerFilter> LocalSpamFilter;
|
||||||
|
public static Option<SpamServerFilter> GlobalSpamFilter;
|
||||||
|
|
||||||
|
public const string LocalFilterComment = @"
|
||||||
|
This file contains a list of filters that can be used to hide servers from the server list.
|
||||||
|
You can add filters by right-clicking a server in the server list and selecting ""Hide server"" or by reporting the server and choosing ""Report and hide server"".
|
||||||
|
The filters are saved in this file, which you can edit manually if you want to.
|
||||||
|
|
||||||
|
The available filter types are:
|
||||||
|
- NameEquals: The server name must equal the specified value. Homoglyphs are also checked.
|
||||||
|
- NameContains: The server name must contain the specified value.
|
||||||
|
- MessageEquals: The server description must equal the specified value. Homoglyphs are also checked.
|
||||||
|
- MessageContains: The server description must contain the specified value.
|
||||||
|
- PlayerCountLarger: The player count must be larger than the specified value.
|
||||||
|
- PlayerCountExact: The player count must match the specified value exactly.
|
||||||
|
- MaxPlayersLarger: The max player count must be larger than the specified value.
|
||||||
|
- MaxPlayersExact: The max player count must match the specified value exactly.
|
||||||
|
- GameModeEquals: The game mode identifier must match the specified value exactly.
|
||||||
|
- PlayStyleEquals: The play style must match the specified value exactly.
|
||||||
|
- Endpoint: The server endpoint, which is a Steam ID or an IP address, must match the specified value exactly. Steam ID is in the format of STEAM_X:Y:Z.
|
||||||
|
- LanguageEquals: The server language must match the specified value exactly.
|
||||||
|
|
||||||
|
The filter values are case-insensitive and adding multiple conditions on one filter will require all of them to be met.
|
||||||
|
Homoglyph comparison is used for NameEquals and MessageEquals filters, which means that it checks whether the words look the same, meaning you can't abuse identical-looking but different symbols to work around the filter. For example ""lmaobox"" and ""lmаobox"" (with a cyrillic a) are considered equal.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
<Filters>
|
||||||
|
<Filter namecontains=""discord.gg"" />
|
||||||
|
<Filter messagecontains=""discord.gg"" />
|
||||||
|
<Filter nameequals=""get good get lmaobox"" maxplayersexact=""999"" />
|
||||||
|
</Filters>
|
||||||
|
These will hide all servers that have a discord.gg link in their name or description and servers with the name ""get good get lmaobox"" that have 999 max players.
|
||||||
|
";
|
||||||
|
static SpamServerFilters()
|
||||||
|
{
|
||||||
|
XDocument? doc;
|
||||||
|
if (!File.Exists(SpamServerFilter.SavePath))
|
||||||
|
{
|
||||||
|
var comment = new XComment(LocalFilterComment);
|
||||||
|
|
||||||
|
doc = new XDocument(comment, new XElement("Filters"));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var writer = XmlWriter.Create(SpamServerFilter.SavePath, new XmlWriterSettings { Indent = true });
|
||||||
|
doc.SaveSafe(writer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError("Saving spam filter failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
doc = XMLExtensions.TryLoadXml(SpamServerFilter.SavePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc?.Root is { } root)
|
||||||
|
{
|
||||||
|
LocalSpamFilter = Option.Some(new SpamServerFilter(root));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsFiltered(ServerInfo info)
|
||||||
|
{
|
||||||
|
if (LocalSpamFilter.TryUnwrap(out var localFilter) && localFilter.IsFiltered(info)) { return true; }
|
||||||
|
if (GlobalSpamFilter.TryUnwrap(out var globalFilter) && globalFilter.IsFiltered(info)) { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddServerToLocalSpamList(ServerInfo info)
|
||||||
|
{
|
||||||
|
if (!LocalSpamFilter.TryUnwrap(out var localFilter)) { return; }
|
||||||
|
if (localFilter.IsFiltered(info)) { return; }
|
||||||
|
|
||||||
|
var filters = localFilter.Filters.Add(new SpamFilter(ImmutableHashSet.Create((NameExact: SpamServerFilterType.NameEquals, info.ServerName))));
|
||||||
|
var newFilter = new SpamServerFilter(filters);
|
||||||
|
newFilter.Save(SpamServerFilter.SavePath);
|
||||||
|
LocalSpamFilter = Option.Some(newFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClearLocalSpamFilter()
|
||||||
|
{
|
||||||
|
var newFilter = new SpamServerFilter(ImmutableArray<SpamFilter>.Empty);
|
||||||
|
newFilter.Save(SpamServerFilter.SavePath);
|
||||||
|
LocalSpamFilter = Option.Some(newFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RequestGlobalSpamFilter()
|
||||||
|
{
|
||||||
|
if (GameSettings.CurrentConfig.DisableGlobalSpamList) { return; }
|
||||||
|
|
||||||
|
string remoteContentUrl = GameSettings.CurrentConfig.RemoteMainMenuContentUrl;
|
||||||
|
if (string.IsNullOrEmpty(remoteContentUrl)) { return; }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = new RestClient($"{remoteContentUrl}spamfilter")
|
||||||
|
{
|
||||||
|
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore)
|
||||||
|
};
|
||||||
|
client.AddDefaultHeader("Cache-Control", "no-cache");
|
||||||
|
client.AddDefaultHeader("Pragma", "no-cache");
|
||||||
|
var request = new RestRequest("serve_spamlist.php", Method.GET);
|
||||||
|
TaskPool.Add("RequestGlobalSpamFilter", client.ExecuteAsync(request), RemoteContentReceived);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("Fetching global spam list failed.", e);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("SpamServerFilters.RequestGlobalSpamFilter:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
|
"Fetching global spam list failed. " + e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemoteContentReceived(Task t)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!t.TryGetResult(out IRestResponse remoteContentResponse)) { throw new Exception("Task did not return a valid result"); }
|
||||||
|
if (remoteContentResponse.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
DebugConsole.AddWarning(
|
||||||
|
"Failed to receive global spam filter." +
|
||||||
|
"There may be an issue with your internet connection, or the master server might be temporarily unavailable " +
|
||||||
|
$"(error code: {remoteContentResponse.StatusCode})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string data = remoteContentResponse.Content;
|
||||||
|
if (string.IsNullOrWhiteSpace(data)) { return; }
|
||||||
|
|
||||||
|
if (XDocument.Parse(data).Root is { } root)
|
||||||
|
{
|
||||||
|
GlobalSpamFilter = Option.Some(new SpamServerFilter(root));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("Reading received global spam filter failed.", e);
|
||||||
|
#endif
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("SpamServerFilters.RemoteContentReceived:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||||
|
"Reading received global spam filter failed. " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,7 +111,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn)
|
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn)
|
||||||
{
|
{
|
||||||
texture = LoadTexture(FilePath.Value, Compress);
|
texture = LoadTexture(FilePath.Value, Compress, contentPackage: SourceElement?.ContentPackage);
|
||||||
|
|
||||||
if (texture == null)
|
if (texture == null)
|
||||||
{
|
{
|
||||||
@@ -175,7 +175,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
texture.Dispose();
|
texture.Dispose();
|
||||||
texture = TextureLoader.FromFile(FilePath.Value, Compress);
|
texture = TextureLoader.FromFile(FilePath.Value, Compress, contentPackage: SourceElement?.ContentPackage);
|
||||||
Identifier pathKey = FullPath.ToIdentifier();
|
Identifier pathKey = FullPath.ToIdentifier();
|
||||||
if (textureRefCounts.ContainsKey(pathKey))
|
if (textureRefCounts.ContainsKey(pathKey))
|
||||||
{
|
{
|
||||||
@@ -195,7 +195,7 @@ namespace Barotrauma
|
|||||||
sourceRect = new Rectangle(0, 0, texture.Width, texture.Height);
|
sourceRect = new Rectangle(0, 0, texture.Width, texture.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Texture2D LoadTexture(string file, bool compress = true)
|
public static Texture2D LoadTexture(string file, bool compress = true, ContentPackage contentPackage = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(file))
|
if (string.IsNullOrWhiteSpace(file))
|
||||||
{
|
{
|
||||||
@@ -221,11 +221,11 @@ namespace Barotrauma
|
|||||||
if (!ToolBox.IsProperFilenameCase(file))
|
if (!ToolBox.IsProperFilenameCase(file))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!");
|
DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!", contentPackage: contentPackage);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D newTexture = TextureLoader.FromFile(file, compress);
|
Texture2D newTexture = TextureLoader.FromFile(file, compress, contentPackage: contentPackage);
|
||||||
lock (list)
|
lock (list)
|
||||||
{
|
{
|
||||||
if (!textureRefCounts.TryAdd(fullPath,
|
if (!textureRefCounts.TryAdd(fullPath,
|
||||||
@@ -284,17 +284,44 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawTiled(ISpriteBatch spriteBatch, Vector2 position, Vector2 targetSize,
|
public void DrawTiled(ISpriteBatch spriteBatch,
|
||||||
Color? color = null, Vector2? startOffset = null, Vector2? textureScale = null, float? depth = null)
|
Vector2 position,
|
||||||
|
Vector2 targetSize,
|
||||||
|
float rotation = 0f,
|
||||||
|
Vector2? origin = null,
|
||||||
|
Color? color = null,
|
||||||
|
Vector2? startOffset = null,
|
||||||
|
Vector2? textureScale = null,
|
||||||
|
float? depth = null,
|
||||||
|
SpriteEffects? spriteEffects = null)
|
||||||
{
|
{
|
||||||
if (Texture == null) { return; }
|
if (Texture == null) { return; }
|
||||||
|
|
||||||
|
spriteEffects ??= effects;
|
||||||
|
bool flipHorizontal = (spriteEffects.Value & SpriteEffects.FlipHorizontally) != 0;
|
||||||
|
bool flipVertical = (spriteEffects.Value & SpriteEffects.FlipVertically) != 0;
|
||||||
|
|
||||||
|
float addedRotation = rotation + this.rotation;
|
||||||
|
if (flipHorizontal != flipVertical) { addedRotation = -addedRotation; }
|
||||||
|
|
||||||
|
Vector2 advanceX = addedRotation == 0.0f ? Vector2.UnitX : new Vector2((float)Math.Cos(addedRotation), (float)Math.Sin(addedRotation));
|
||||||
|
Vector2 advanceY = new Vector2(-advanceX.Y, advanceX.X);
|
||||||
|
|
||||||
//Init optional values
|
//Init optional values
|
||||||
Vector2 drawOffset = startOffset ?? Vector2.Zero;
|
Vector2 drawOffset = startOffset ?? Vector2.Zero;
|
||||||
Vector2 scale = textureScale ?? Vector2.One;
|
Vector2 scale = textureScale ?? Vector2.One;
|
||||||
Color drawColor = color ?? Color.White;
|
Color drawColor = color ?? Color.White;
|
||||||
|
Vector2 transformedOrigin = origin ?? Vector2.Zero;
|
||||||
|
|
||||||
bool flipHorizontal = (effects & SpriteEffects.FlipHorizontally) != 0;
|
transformedOrigin = advanceX * transformedOrigin.X + advanceY * transformedOrigin.Y;
|
||||||
bool flipVertical = (effects & SpriteEffects.FlipVertically) != 0;
|
|
||||||
|
void drawSection(Vector2 slicePos, Rectangle sliceRect)
|
||||||
|
{
|
||||||
|
Vector2 transformedPos = slicePos - position;
|
||||||
|
transformedPos = advanceX * transformedPos.X + advanceY * transformedPos.Y;
|
||||||
|
transformedPos += position - transformedOrigin;
|
||||||
|
spriteBatch.Draw(texture, transformedPos, sliceRect, drawColor, addedRotation, Vector2.Zero, scale, spriteEffects.Value, depth ?? this.depth);
|
||||||
|
}
|
||||||
|
|
||||||
//wrap the drawOffset inside the sourceRect
|
//wrap the drawOffset inside the sourceRect
|
||||||
drawOffset.X = (drawOffset.X / scale.X) % sourceRect.Width;
|
drawOffset.X = (drawOffset.X / scale.X) % sourceRect.Width;
|
||||||
@@ -368,8 +395,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
slicePos.Y += flippedDrawOffset.Y;
|
slicePos.Y += flippedDrawOffset.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Draw(texture, slicePos, sliceRect, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
|
drawSection(slicePos, sliceRect);
|
||||||
currDrawPosition.X = slicePos.X + sliceWidth;
|
currDrawPosition.X = slicePos.X + sliceWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,7 +443,7 @@ namespace Barotrauma
|
|||||||
sliceRect.Y = SourceRect.Y;
|
sliceRect.Y = SourceRect.Y;
|
||||||
sliceRect.Height = (int)(sliceHeight / scale.Y);
|
sliceRect.Height = (int)(sliceHeight / scale.Y);
|
||||||
|
|
||||||
spriteBatch.Draw(texture, slicePos, sliceRect, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
|
drawSection(slicePos, sliceRect);
|
||||||
|
|
||||||
currDrawPosition.Y = slicePos.Y + sliceHeight;
|
currDrawPosition.Y = slicePos.Y + sliceHeight;
|
||||||
}
|
}
|
||||||
@@ -433,8 +460,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spriteBatch.Draw(texture, currDrawPosition,
|
drawSection(currDrawPosition, texPerspective);
|
||||||
texPerspective, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
|
|
||||||
|
|
||||||
currDrawPosition.Y += texPerspective.Height * scale.Y;
|
currDrawPosition.Y += texPerspective.Height * scale.Y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ namespace Barotrauma
|
|||||||
statusEffect.soundChannel.FadeOutAndDispose();
|
statusEffect.soundChannel.FadeOutAndDispose();
|
||||||
statusEffect.soundChannel = null;
|
statusEffect.soundChannel = null;
|
||||||
}
|
}
|
||||||
else
|
else if (statusEffect.soundEmitter is { Removed: false })
|
||||||
{
|
{
|
||||||
statusEffect.soundChannel.Position = new Vector3(statusEffect.soundEmitter.WorldPosition, 0.0f);
|
statusEffect.soundChannel.Position = new Vector3(statusEffect.soundEmitter.WorldPosition, 0.0f);
|
||||||
if (doMuffleCheck && !statusEffect.ignoreMuffling)
|
if (doMuffleCheck && !statusEffect.ignoreMuffling)
|
||||||
|
|||||||
@@ -101,13 +101,36 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
Color = GUIStyle.Green
|
Color = GUIStyle.Green
|
||||||
};
|
};
|
||||||
|
var textShadow = new GUITextBlock(new RectTransform(Vector2.One, itemDownloadProgress.RectTransform) { AbsoluteOffset = new Point(GUI.IntScale(3)) }, "",
|
||||||
|
textColor: Color.Black, textAlignment: Alignment.Center);
|
||||||
|
var text = new GUITextBlock(new RectTransform(Vector2.One, itemDownloadProgress.RectTransform), "",
|
||||||
|
textAlignment: Alignment.Center);
|
||||||
var itemDownloadProgressUpdater = new GUICustomComponent(
|
var itemDownloadProgressUpdater = new GUICustomComponent(
|
||||||
new RectTransform(Vector2.Zero, msgBox.Content.RectTransform),
|
new RectTransform(Vector2.Zero, msgBox.Content.RectTransform),
|
||||||
onUpdate: (f, component) =>
|
onUpdate: (f, component) =>
|
||||||
{
|
{
|
||||||
float progress = 0.0f;
|
float progress = 0.0f;
|
||||||
if (item.IsDownloading) { progress = item.DownloadAmount; }
|
if (item.IsDownloading)
|
||||||
else if (itemDownloadProgress.BarSize > 0.0f) { progress = 1.0f; }
|
{
|
||||||
|
progress = item.DownloadAmount;
|
||||||
|
text.Text = textShadow.Text = TextManager.GetWithVariable(
|
||||||
|
"PublishPopupDownload",
|
||||||
|
"[percentage]",
|
||||||
|
((int)MathF.Round(item.DownloadAmount * 100)).ToString());
|
||||||
|
}
|
||||||
|
else if (itemDownloadProgress.BarSize > 0.0f)
|
||||||
|
{
|
||||||
|
if (!item.IsInstalled && !SteamManager.Workshop.CanBeInstalled(item.Id))
|
||||||
|
{
|
||||||
|
itemDownloadProgress.Color = GUIStyle.Red;
|
||||||
|
text.Text = textShadow.Text = TextManager.Get("workshopiteminstallfailed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text.Text = textShadow.Text = TextManager.Get(item.IsInstalled ? "workshopiteminstalled" : "PublishPopupInstall");
|
||||||
|
}
|
||||||
|
progress = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
itemDownloadProgress.BarSize = Math.Max(itemDownloadProgress.BarSize,
|
itemDownloadProgress.BarSize = Math.Max(itemDownloadProgress.BarSize,
|
||||||
MathHelper.Lerp(itemDownloadProgress.BarSize, progress, 0.1f));
|
MathHelper.Lerp(itemDownloadProgress.BarSize, progress, 0.1f));
|
||||||
@@ -134,9 +157,16 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
foreach (var item in itemsToDownload)
|
foreach (var item in itemsToDownload)
|
||||||
{
|
{
|
||||||
|
DebugConsole.Log($"Reinstalling {item.Title}...");
|
||||||
await SteamManager.Workshop.Reinstall(item);
|
await SteamManager.Workshop.Reinstall(item);
|
||||||
if (!GUIMessageBox.MessageBoxes.Contains(msgBox)) { break; }
|
DebugConsole.Log($"Finished installing {item.Title}...");
|
||||||
|
if (!GUIMessageBox.MessageBoxes.Contains(msgBox))
|
||||||
|
{
|
||||||
|
DebugConsole.Log($"Download prompt closed, interrupting {nameof(DownloadItems)}.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
DebugConsole.Log($"{nameof(DownloadItems)} finished.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ namespace Barotrauma.Steam
|
|||||||
currentLobby?.SetData("playstyle", serverSettings.PlayStyle.ToString());
|
currentLobby?.SetData("playstyle", serverSettings.PlayStyle.ToString());
|
||||||
currentLobby?.SetData("gamemode", GameMain.NetLobbyScreen?.SelectedMode?.Identifier.Value ?? "");
|
currentLobby?.SetData("gamemode", GameMain.NetLobbyScreen?.SelectedMode?.Identifier.Value ?? "");
|
||||||
currentLobby?.SetData("language", serverSettings.Language.ToString());
|
currentLobby?.SetData("language", serverSettings.Language.ToString());
|
||||||
|
if (GameMain.NetLobbyScreen?.SelectedSub != null)
|
||||||
|
{
|
||||||
|
currentLobby?.SetData("submarine", GameMain.NetLobbyScreen.SelectedSub.Name);
|
||||||
|
}
|
||||||
|
|
||||||
DebugConsole.Log("Lobby updated!");
|
DebugConsole.Log("Lobby updated!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
public static void OnItemDownloadComplete(ulong id, bool forceInstall = false)
|
public static void OnItemDownloadComplete(ulong id, bool forceInstall = false)
|
||||||
{
|
{
|
||||||
if (!(Screen.Selected is MainMenuScreen) && !forceInstall)
|
if (Screen.Selected is not MainMenuScreen && !forceInstall)
|
||||||
{
|
{
|
||||||
if (!MainMenuScreen.WorkshopItemsToUpdate.Contains(id))
|
if (!MainMenuScreen.WorkshopItemsToUpdate.Contains(id))
|
||||||
{
|
{
|
||||||
@@ -306,13 +306,26 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (CanBeInstalled(id)
|
else if (!CanBeInstalled(id))
|
||||||
&& !ContentPackageManager.WorkshopPackages.Any(p =>
|
{
|
||||||
|
DebugConsole.Log($"Cannot install {id}");
|
||||||
|
InstallWaiter.StopWaiting(id);
|
||||||
|
}
|
||||||
|
else if (ContentPackageManager.WorkshopPackages.Any(p =>
|
||||||
p.UgcId.TryUnwrap(out var ugcId)
|
p.UgcId.TryUnwrap(out var ugcId)
|
||||||
&& ugcId is SteamWorkshopId workshopId
|
&& ugcId is SteamWorkshopId workshopId
|
||||||
&& workshopId.Value == id)
|
&& workshopId.Value == id))
|
||||||
&& !InstallTaskCounter.IsInstalling(id))
|
|
||||||
{
|
{
|
||||||
|
DebugConsole.Log($"Already installed {id}.");
|
||||||
|
InstallWaiter.StopWaiting(id);
|
||||||
|
}
|
||||||
|
else if (InstallTaskCounter.IsInstalling(id))
|
||||||
|
{
|
||||||
|
DebugConsole.Log($"Already installing {id}.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugConsole.Log($"Finished downloading {id}, installing...");
|
||||||
TaskPool.Add($"InstallItem{id}", InstallMod(id), t => InstallWaiter.StopWaiting(id));
|
TaskPool.Add($"InstallItem{id}", InstallMod(id), t => InstallWaiter.StopWaiting(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user