(8f9250974) Fix spritesheet orientation offestting the joint widgets in the wrong direction, which made it a bit difficult to use.

This commit is contained in:
Joonas Rikkonen
2019-03-27 20:54:00 +02:00
parent ad1a726e91
commit 4cb3469c4f
40 changed files with 634 additions and 960 deletions

View File

@@ -79,8 +79,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\ParamsEditor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\RectTransform.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\ShapeExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\SpriteSheetPlayer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\UISprite.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\VideoPlayer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\GUI\Widget.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\Items\CharacterInventory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Source\Items\Components\Door.cs" />

View File

@@ -16,13 +16,14 @@ namespace Barotrauma
if (SelectedAiTarget?.Entity != null)
{
GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.3f, 0, 5);
GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.5f, 0, 4);
if (wallTarget != null)
{
Vector2 wallTargetPos = wallTarget.Position;
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
wallTargetPos.Y = -wallTargetPos.Y;
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false);
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false);
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
}
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.FormatZeroDecimal()})", Color.Red, Color.Black);
@@ -56,18 +57,16 @@ namespace Barotrauma
{
GUI.DrawLine(spriteBatch,
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorA.X, -attachJoint.WorldAnchorA.Y)),
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Orange * 0.6f, 0, 5);
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Green, 0, 4);
}
if (latchOntoAI.WallAttachPos.HasValue)
{
GUI.DrawLine(spriteBatch, pos,
ConvertUnits.ToDisplayUnits(new Vector2(latchOntoAI.WallAttachPos.Value.X, -latchOntoAI.WallAttachPos.Value.Y)), Color.Orange * 0.6f, 0, 3);
ConvertUnits.ToDisplayUnits(new Vector2(latchOntoAI.WallAttachPos.Value.X, -latchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3);
}
}
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Steering.X, -Steering.Y)), Color.Blue, width: 3);
if (steeringManager is IndoorsSteeringManager pathSteering)
{
var path = pathSteering.CurrentPath;

View File

@@ -68,14 +68,6 @@ namespace Barotrauma
private float dropItemAnimDuration = 0.5f;
private float dropItemAnimTimer;
public Item DroppedItem
{
get
{
return droppedItem;
}
}
private Item droppedItem;
private GUIComponent draggingMed;

View File

@@ -1815,6 +1815,189 @@ namespace Barotrauma
NPCConversation.WriteToCSV();
}));
commands.Add(new Command("csvtoxml", "csvtoxml [language] -> Converts .csv localization files in Content/NPCConversations & Content/Texts to .xml for use in-game.", (string[] args) =>
{
if (args.Length == 0) return;
LocalizationCSVtoXML.Convert(args[0]);
}));
#endif
commands.Add(new Command("cleanbuild", "", (string[] args) =>
{
float defaultZoom = Screen.Selected.Cam.DefaultZoom;
if (args.Length > 0) float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out defaultZoom);
float zoomSmoothness = Screen.Selected.Cam.ZoomSmoothness;
if (args.Length > 1) float.TryParse(args[1], NumberStyles.Number, CultureInfo.InvariantCulture, out zoomSmoothness);
float moveSmoothness = Screen.Selected.Cam.MoveSmoothness;
if (args.Length > 2) float.TryParse(args[2], NumberStyles.Number, CultureInfo.InvariantCulture, out moveSmoothness);
float minZoom = Screen.Selected.Cam.MinZoom;
if (args.Length > 3) float.TryParse(args[3], NumberStyles.Number, CultureInfo.InvariantCulture, out minZoom);
float maxZoom = Screen.Selected.Cam.MaxZoom;
if (args.Length > 4) float.TryParse(args[4], NumberStyles.Number, CultureInfo.InvariantCulture, out maxZoom);
Screen.Selected.Cam.DefaultZoom = defaultZoom;
Screen.Selected.Cam.ZoomSmoothness = zoomSmoothness;
Screen.Selected.Cam.MoveSmoothness = moveSmoothness;
Screen.Selected.Cam.MinZoom = minZoom;
Screen.Selected.Cam.MaxZoom = maxZoom;
}));
commands.Add(new Command("waterparams", "waterparams [distortionscalex] [distortionscaley] [distortionstrengthx] [distortionstrengthy] [bluramount]: default 0.5 0.5 0.5 0.5 1", (string[] args) =>
{
float distortScaleX = 0.5f, distortScaleY = 0.5f;
float distortStrengthX = 0.5f, distortStrengthY = 0.5f;
float blurAmount = 0.0f;
if (args.Length > 0) float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out distortScaleX);
if (args.Length > 1) float.TryParse(args[1], NumberStyles.Number, CultureInfo.InvariantCulture, out distortScaleY);
if (args.Length > 2) float.TryParse(args[2], NumberStyles.Number, CultureInfo.InvariantCulture, out distortStrengthX);
if (args.Length > 3) float.TryParse(args[3], NumberStyles.Number, CultureInfo.InvariantCulture, out distortStrengthY);
if (args.Length > 4) float.TryParse(args[4], NumberStyles.Number, CultureInfo.InvariantCulture, out blurAmount);
WaterRenderer.DistortionScale = new Vector2(distortScaleX, distortScaleY);
WaterRenderer.DistortionStrength = new Vector2(distortStrengthX, distortStrengthY);
WaterRenderer.BlurAmount = blurAmount;
}));
commands.Add(new Command("refreshrect", "Updates the dimensions of the selected items to match the ones defined in the prefab. Applied only in the subeditor.", (string[] args) =>
{
//TODO: maybe do this automatically during loading when possible?
if (Screen.Selected == GameMain.SubEditorScreen)
{
if (!MapEntity.SelectedAny)
{
ThrowError("You have to select item(s) first!");
}
else
{
foreach (var mapEntity in MapEntity.SelectedList)
{
if (mapEntity is Item item)
{
item.Rect = new Rectangle(item.Rect.X, item.Rect.Y,
(int)(item.Prefab.sprite.size.X * item.Prefab.Scale),
(int)(item.Prefab.sprite.size.Y * item.Prefab.Scale));
}
else if (mapEntity is Structure structure)
{
if (!structure.ResizeHorizontal)
{
structure.Rect = new Rectangle(structure.Rect.X, structure.Rect.Y,
(int)structure.Prefab.ScaledSize.X,
structure.Rect.Height);
}
if (!structure.ResizeVertical)
{
structure.Rect = new Rectangle(structure.Rect.X, structure.Rect.Y,
structure.Rect.Width,
(int)structure.Prefab.ScaledSize.Y);
}
}
}
}
}
}, isCheat: false));
#endif
GameMain.Config.SaveNewPlayerConfig();
commands.Add(new Command("loadtexts", "loadtexts [sourcefile] [destinationfile]: Loads all lines of text from a given .txt file and inserts them sequientially into the elements of an xml file. If the file paths are omitted, EnglishVanilla.txt and EnglishVanilla.xml are used.", (string[] args) =>
{
string sourcePath = args.Length > 0 ? args[0] : "Content/Texts/EnglishVanilla.txt";
string destinationPath = args.Length > 1 ? args[1] : "Content/Texts/EnglishVanilla.xml";
string[] lines;
try
{
lines = File.ReadAllLines(sourcePath);
}
catch (Exception e)
{
ThrowError("Reading the file \"" + sourcePath + "\" failed.", e);
return;
}
var doc = XMLExtensions.TryLoadXml(destinationPath);
int i = 0;
foreach (XElement element in doc.Root.Elements())
{
if (i >= lines.Length)
{
ThrowError("Error while loading texts to the xml file. The xml has more elements than the number of lines in the text file.");
return;
}
element.Value = lines[i];
i++;
}
doc.Save(destinationPath);
},
() =>
{
var files = TextManager.GetTextFiles().Select(f => f.Replace("\\", "/"));
return new string[][]
{
files.Where(f => Path.GetExtension(f)==".txt").ToArray(),
files.Where(f => Path.GetExtension(f)==".xml").ToArray()
};
}));
commands.Add(new Command("updatetextfile", "updatetextfile [sourcefile] [destinationfile]: Inserts all the xml elements that are only present in the source file into the destination file. Can be used to update outdated translation files more easily.", (string[] args) =>
{
if (args.Length < 2) return;
string sourcePath = args[0];
string destinationPath = args[1];
var sourceDoc = XMLExtensions.TryLoadXml(sourcePath);
var destinationDoc = XMLExtensions.TryLoadXml(destinationPath);
XElement destinationElement = destinationDoc.Root.Elements().First();
foreach (XElement element in sourceDoc.Root.Elements())
{
if (destinationDoc.Root.Element(element.Name) == null)
{
element.Value = "!!!!!!!!!!!!!" + element.Value;
destinationElement.AddAfterSelf(element);
}
XNode nextNode = destinationElement.NextNode;
while ((!(nextNode is XElement) || nextNode == element) && nextNode != null) nextNode = nextNode.NextNode;
destinationElement = nextNode as XElement;
}
destinationDoc.Save(destinationPath);
},
() =>
{
var files = TextManager.GetTextFiles().Where(f => Path.GetExtension(f) == ".xml").Select(f => f.Replace("\\", "/")).ToArray();
return new string[][]
{
files,
files
};
}));
commands.Add(new Command("dumpentitytexts", "dumpentitytexts [filepath]: gets the names and descriptions of all entity prefabs and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EntityTexts.txt", (string[] args) =>
{
string filePath = args.Length > 0 ? args[0] : "Content/Texts/EntityTexts.txt";
List<string> lines = new List<string>();
foreach (MapEntityPrefab me in MapEntityPrefab.List)
{
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</" + me.Identifier + ".Name>");
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</" + me.Identifier + ".Description>");
}
File.WriteAllLines(filePath, lines);
}));
#if DEBUG
commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) =>
{
if (args.Length != 1) return;
TextManager.CheckForDuplicates(args[0]);
}));
commands.Add(new Command("writetocsv", "Writes the default language (English) to a .csv file.", (string[] args) =>
{
TextManager.WriteToCSV();
NPCConversation.WriteToCSV();
}));
commands.Add(new Command("csvtoxml", "csvtoxml [language] -> Converts .csv localization files in Content/NPCConversations & Content/Texts to .xml for use in-game.", (string[] args) =>
{
if (args.Length == 0) return;

View File

@@ -69,9 +69,6 @@ namespace Barotrauma
public static ScalableFont Font => Style?.Font;
public static ScalableFont SmallFont => Style?.SmallFont;
public static ScalableFont LargeFont => Style?.LargeFont;
public static ScalableFont VideoTitleFont => Style?.VideoTitleFont;
public static ScalableFont ObjectiveTitleFont => Style?.ObjectiveTitleFont;
public static ScalableFont ObjectiveNameFont => Style?.ObjectiveNameFont;
public static UISprite UIGlow => Style.UIGlow;
@@ -533,19 +530,14 @@ namespace Barotrauma
if (list.Count == 0) { return; }
foreach (var item in list)
{
int index = 0;
if (updateList.Count > 0)
int i = updateList.Count - 1;
while (updateList[i].UpdateOrder > item.UpdateOrder)
{
index = updateList.Count - 1;
while (updateList[index].UpdateOrder > item.UpdateOrder)
{
index--;
if (index == 0) { break; }
}
i--;
}
if (!updateListSet.Contains(item))
{
updateList.Insert(index, item);
updateList.Insert(Math.Max(i, 0), item);
updateListSet.Add(item);
}
}
@@ -656,21 +648,6 @@ namespace Barotrauma
msg.Timer -= deltaTime;
msg.Pos += msg.Velocity * deltaTime;
}
foreach (GUIMessage msg in messages)
{
if (!msg.WorldSpace) continue;
msg.Timer -= deltaTime;
msg.Pos += msg.Velocity * deltaTime;
}
foreach (GUIMessage msg in messages)
{
if (!msg.WorldSpace) continue;
msg.Timer -= deltaTime;
msg.Pos += msg.Velocity * deltaTime;
}
}
messages.RemoveAll(m => m.Timer <= 0.0f);
}
@@ -744,10 +721,6 @@ namespace Barotrauma
Vector2 textSize = font.MeasureString(text);
DrawRectangle(sb, pos - Vector2.One * backgroundPadding, textSize + Vector2.One * 2.0f * backgroundPadding, (Color)backgroundColor, true);
}
else
{
sb.Draw(t, new Rectangle(rect.X + thickness, rect.Y, rect.Width - thickness * 2, thickness), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
sb.Draw(t, new Rectangle(rect.X + thickness, rect.Y + rect.Height - thickness, rect.Width - thickness * 2, thickness), null, clr, 0.0f, Vector2.Zero, SpriteEffects.None, depth);
font.DrawString(sb, text, pos, color);
}

View File

@@ -12,9 +12,6 @@ namespace Barotrauma
public ScalableFont Font { get; private set; }
public ScalableFont SmallFont { get; private set; }
public ScalableFont LargeFont { get; private set; }
public ScalableFont VideoTitleFont { get; private set; }
public ScalableFont ObjectiveTitleFont { get; private set; }
public ScalableFont ObjectiveNameFont { get; private set; }
public Sprite CursorSprite { get; private set; }
@@ -51,15 +48,6 @@ namespace Barotrauma
case "largefont":
LargeFont = new ScalableFont(subElement, graphicsDevice);
break;
case "objectivetitle":
ObjectiveTitleFont = new ScalableFont(subElement, graphicsDevice);
break;
case "objectivename":
ObjectiveNameFont = new ScalableFont(subElement, graphicsDevice);
break;
case "videotitle":
VideoTitleFont = new ScalableFont(subElement, graphicsDevice);
break;
case "cursor":
CursorSprite = new Sprite(subElement);
break;

View File

@@ -50,11 +50,6 @@ namespace Barotrauma
get; private set;
}
public static Rectangle ObjectiveAnchor
{
get; private set;
}
public static Rectangle InventoryAreaLower
{
get; private set;
@@ -161,10 +156,6 @@ namespace Barotrauma
new Rectangle(Padding, CrewArea.Y, chatBoxWidth, chatBoxHeight) :
new Rectangle(GameMain.GraphicsWidth - Padding - chatBoxWidth, CrewArea.Y, chatBoxWidth, chatBoxHeight);
int objectiveAnchorWidth = (int)(250 * GUI.Scale);
int objectiveAnchorOffsetY = (int)(100 * GUI.Scale);
ObjectiveAnchor = new Rectangle(GameMain.GraphicsWidth - Padding - objectiveAnchorWidth, CrewArea.Y + crewAreaHeight + objectiveAnchorOffsetY, objectiveAnchorWidth, 0);
int lowerAreaHeight = (int)Math.Min(GameMain.GraphicsHeight * 0.25f, 280);
InventoryAreaLower = new Rectangle(Padding, GameMain.GraphicsHeight - lowerAreaHeight, GameMain.GraphicsWidth - Padding * 2, lowerAreaHeight);

View File

@@ -44,7 +44,7 @@ namespace Barotrauma
ContextualTutorial = Tutorial.Tutorials.Find(t => t is ContextualTutorial) as ContextualTutorial;
if (ContextualTutorial.Selected) // Selected when starting a new game -> initialize
if (ContextualTutorial.Selected && !ContextualTutorial.Initialized) // Selected when starting a new game -> initialize
{
ContextualTutorial.Initialize();
}

View File

@@ -1,10 +1,9 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Xml.Linq;
using System;
using Microsoft.Xna.Framework;
using Barotrauma.Items.Components;
using System.Linq;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma.Tutorials
{
@@ -14,60 +13,38 @@ namespace Barotrauma.Tutorials
public static bool ContentRunning = false;
public static bool Initialized = false;
private enum ContentTypes { None = 0, Video = 1, TextOnly = 2 };
private enum ContentTypes { None = 0, Video = 1, Text = 2 };
private TutorialSegment activeSegment;
private List<TutorialSegment> segments;
private VideoPlayer videoPlayer;
private SpriteSheetPlayer spriteSheetPlayer;
private Steering navConsole;
private Reactor reactor;
private Sonar sonar;
private Vector2 subStartingPosition;
private List<Character> crew;
private Character mechanic;
private Character engineer;
private Character injuredMember = null;
private List<Pair<Character, float>> characterTimeOnSonar;
private float requiredTimeOnSonar = 5f;
private bool started = false;
private string playableContentPath;
private float tutorialTimer;
private float degrading2ActivationCountdown;
private bool disableTutorialOnDeficiencyFound = true;
private GUIFrame holderFrame, objectiveFrame;
//private GUIButton toggleButton;
//private bool objectivesOpen = false;
//private float openState = 0f;
private List<TutorialSegment> activeObjectives = new List<TutorialSegment>();
private string objectiveTranslated;
//private Point objectiveBaseOffset = Point.Zero;
private float floodTutorialTimer = 0.0f;
private const float floodTutorialDelay = 2.0f;
private float medicalTutorialTimer = 0.0f;
private const float medicalTutorialDelay = 2.0f;
private class TutorialSegment
{
public string Id;
public string Objective;
public string Name;
public ContentTypes ContentType;
public XElement TextContent;
public XElement VideoContent;
public XElement Content;
public bool IsTriggered;
public GUIButton ReplayButton;
public GUITextBlock LinkedTitle, LinkedText;
public TutorialSegment(XElement config)
{
Id = config.GetAttributeString("id", "Missing ID");
Objective = TextManager.Get(config.GetAttributeString("objective", string.Empty), true);
Name = config.GetAttributeString("name", "Missing Name");
Enum.TryParse(config.GetAttributeString("contenttype", "None"), true, out ContentType);
IsTriggered = config.GetAttributeBool("istriggered", false);
@@ -76,11 +53,10 @@ namespace Barotrauma.Tutorials
case ContentTypes.None:
break;
case ContentTypes.Video:
VideoContent = config.Element("Video");
TextContent = config.Element("Text");
Content = config.Element("Video");
break;
case ContentTypes.TextOnly:
TextContent = config.Element("Text");
case ContentTypes.Text:
Content = config.Element("Text");
break;
}
}
@@ -101,18 +77,17 @@ namespace Barotrauma.Tutorials
public override void Initialize()
{
for (int i = 0; i < segments.Count; i++)
{
segments[i].IsTriggered = false;
}
if (Initialized) return;
Initialized = true;
base.Initialize();
videoPlayer = new VideoPlayer();
spriteSheetPlayer = new SpriteSheetPlayer();
characterTimeOnSonar = new List<Pair<Character, float>>();
//objectivesOpen = true;
for (int i = 0; i < segments.Count; i++)
{
segments[i].IsTriggered = false;
}
}
public void LoadPartiallyComplete(XElement element)
@@ -136,13 +111,13 @@ namespace Barotrauma.Tutorials
}
}
private void PreloadVideoContent() // Have to see if needed with videos
private void PreloadVideoContent()
{
/*for (int i = 0; i < segments.Count; i++)
for (int i = 0; i < segments.Count; i++)
{
if (segments[i].ContentType != ContentTypes.Video || segments[i].IsTriggered) continue;
spriteSheetPlayer.PreloadContent(playableContentPath, "tutorial", segments[i].Id, segments[i].VideoContent);
}*/
spriteSheetPlayer.PreloadContent(playableContentPath, "tutorial", segments[i].Name, segments[i].Content);
}
}
public void SavePartiallyComplete(XElement element)
@@ -180,12 +155,9 @@ namespace Barotrauma.Tutorials
base.Start();
injuredMember = null;
activeObjectives.Clear();
objectiveTranslated = TextManager.Get("Objective");
CreateObjectiveFrame();
activeSegment = null;
tutorialTimer = floodTutorialTimer = medicalTutorialTimer = 0.0f;
tutorialTimer = 0.0f;
degrading2ActivationCountdown = -1;
subStartingPosition = Vector2.Zero;
characterTimeOnSonar.Clear();
@@ -221,9 +193,6 @@ namespace Barotrauma.Tutorials
}
crew = GameMain.GameSession.CrewManager.GetCharacters().ToList();
mechanic = CrewMemberWithJob("mechanic");
engineer = CrewMemberWithJob("engineer");
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
started = true;
}
@@ -239,196 +208,71 @@ namespace Barotrauma.Tutorials
public void Stop()
{
started = ContentRunning = Initialized = false;
videoPlayer.Remove();
videoPlayer = null;
spriteSheetPlayer.Remove();
spriteSheetPlayer = null;
characterTimeOnSonar = null;
}
private void CreateObjectiveFrame()
{
holderFrame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center));
objectiveFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ObjectiveAnchor, holderFrame.RectTransform), style: null);
/*int toggleButtonWidth = (int)(30 * GUI.Scale);
int toggleButtonHeight = (int)(40 * GUI.Scale);
toggleButton = new GUIButton(new RectTransform(new Point(toggleButtonWidth, toggleButtonHeight), objectiveFrame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(0, 20) }, style: "UIToggleButton");
toggleButton.OnClicked += (GUIButton btn, object userdata) =>
{
objectivesOpen = !objectivesOpen;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = objectivesOpen ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
}
return true;
};
objectiveBaseOffset = new Point((int)(-2.5f * toggleButton.Rect.Width), 0);*/
}
public override void AddToGUIUpdateList()
{
if (objectiveFrame != null && activeObjectives.Count > 0)
{
objectiveFrame.AddToGUIUpdateList(order: -1);
}
base.AddToGUIUpdateList();
if (videoPlayer != null)
if (spriteSheetPlayer != null)
{
videoPlayer.AddToGUIUpdateList(order: 100);
spriteSheetPlayer.AddToGUIUpdateList();
}
}
public override void Update(float deltaTime)
{
if (videoPlayer != null)
{
videoPlayer.Update();
}
if (infoBox != null)
{
if (PlayerInput.KeyHit(Keys.Enter) || PlayerInput.KeyHit(Keys.Escape))
{
CloseInfoFrame(null, null);
}
}
if (!started || ContentRunning) return;
deltaTime *= 0.5f;
for (int i = 0; i < segments.Count; i++)
{
if (segments[i].IsTriggered || activeObjectives.Contains(segments[i])) continue;
if (segments[i].IsTriggered) continue;
if (CheckContextualTutorials(i, deltaTime)) // Found a relevant tutorial, halt finding new ones
{
break;
}
}
for (int i = 0; i < activeObjectives.Count; i++)
{
CheckActiveObjectives(activeObjectives[i], deltaTime);
}
/*if (activeObjectives.Count > 0)
{
if (objectivesOpen)
{
openState -= deltaTime * 5.0f;
}
else
{
openState += deltaTime * 5.0f;
}
openState = MathHelper.Clamp(openState, 0.0f, 1.0f);
float widestObjective = 0f;
for (int i = 0; i < activeObjectives.Count; i++)
{
if (activeObjectives[i].ReplayButton.Rect.Width > widestObjective)
{
widestObjective = activeObjectives[i].ReplayButton.Rect.Width;
}
}
float objectivesHiddenOffset = widestObjective + toggleButton.Rect.Width + 100f;
for (int i = 0; i < activeObjectives.Count; i++)
{
activeObjectives[i].ReplayButton.RectTransform.AbsoluteOffset = objectiveBaseOffset + new Point((int)MathHelper.SmoothStep(0, objectivesHiddenOffset, openState), 0);
}
}*/
}
private void ClosePreTextAndTriggerVideoCallback()
{
if (!string.IsNullOrEmpty(activeSegment.Objective))
{
videoPlayer.LoadContentWithObjective(playableContentPath, new VideoPlayer.VideoSettings(activeSegment.VideoContent), new VideoPlayer.TextSettings(activeSegment.VideoContent), activeSegment.Id, true, activeSegment.Objective, CurrentSegmentStopCallback);
}
else
{
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(activeSegment.VideoContent), new VideoPlayer.TextSettings(activeSegment.VideoContent), activeSegment.Id, true, CurrentSegmentStopCallback);
}
}
private void CurrentSegmentStopCallback()
{
if (!string.IsNullOrEmpty(activeSegment.Objective))
{
AddNewObjective(activeSegment);
}
activeSegment = null;
ContentRunning = false;
}
private void AddNewObjective(TutorialSegment segment)
{
activeObjectives.Add(segment);
Point replayButtonSize = new Point((int)GUI.ObjectiveNameFont.MeasureString(segment.Objective).X, (int)(GUI.ObjectiveNameFont.MeasureString(segment.Objective).Y * 1.45f));
segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopRight, Pivot.TopRight) { AbsoluteOffset = new Point(/*(int)(-2.5f * toggleButton.Rect.Width)*/0, (replayButtonSize.Y + 20) * (activeObjectives.Count - 1)) }, style: null);
segment.ReplayButton.OnClicked += (GUIButton btn, object userdata) =>
{
ReplaySegmentVideo(segment);
return true;
};
int yOffset = (int)(GUI.ObjectiveNameFont.MeasureString(objectiveTranslated).Y / 2f) + 5;
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point(replayButtonSize.X, yOffset), segment.ReplayButton.RectTransform, Anchor.Center, Pivot.BottomCenter) { AbsoluteOffset = new Point(10, 0) }, objectiveTranslated, textColor: Color.White, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight);
segment.LinkedText = new GUITextBlock(new RectTransform(new Point(replayButtonSize.X, yOffset), segment.ReplayButton.RectTransform, Anchor.Center, Pivot.TopCenter) { AbsoluteOffset = new Point(10, 0) }, segment.Objective, textColor: new Color(4, 180, 108), font: GUI.ObjectiveNameFont, textAlignment: Alignment.CenterRight);
segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent;
segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent;
segment.ReplayButton.Color = segment.ReplayButton.HoverColor = segment.ReplayButton.PressedColor = segment.ReplayButton.SelectedColor = Color.Transparent;
}
private void RemoveCompletedObjective(TutorialSegment objective)
{
objectiveFrame.RemoveChild(objective.ReplayButton);
activeObjectives.Remove(objective);
objective.IsTriggered = true;
for (int i = 0; i < activeObjectives.Count; i++)
{
activeObjectives[i].ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjectives[i].ReplayButton.Rect.Height + 20) * i);
}
}
private bool CheckContextualTutorials(int index, float deltaTime)
{
switch (index)
{
case 0: // Welcome: Game Start [Text]
if (tutorialTimer < 1.0f)
if (tutorialTimer < 0.5f)
{
tutorialTimer += deltaTime;
return false;
}
break;
case 1: // Command Reactor: 2 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
if (!segments[0].IsTriggered) return false;
if (tutorialTimer < 3.0f)
case 1: // Command Reactor: 10 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
if (tutorialTimer < 10.5f)
{
tutorialTimer += deltaTime;
if (HasOrder("operatereactor"))
{
segments[index].IsTriggered = true;
tutorialTimer = 2.5f;
tutorialTimer = 10.5f;
}
return false;
}
break;
case 2: // Nav Console: 2 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
if (!IsReactorPoweredUp()) return false; // Do not advance tutorial based on this segment if reactor has not been powered up
case 2: // Nav Console: 20 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
if (Character.Controlled?.SelectedConstruction != navConsole.Item)
{
if (tutorialTimer < 4.5f)
{
if (!segments[1].IsTriggered) return false; // Do not advance tutorial timer based on this segment if reactor has not been powered up
if (tutorialTimer < 30.5f)
{
tutorialTimer += deltaTime;
return false;
@@ -436,13 +280,20 @@ namespace Barotrauma.Tutorials
}
else
{
tutorialTimer = 4.5f;
}
if (!segments[1].IsTriggered || !HasOrder("operatereactor")) // If reactor has not been powered up or ordered to be, default to that one first
{
if (tutorialTimer < 10.5f)
{
tutorialTimer = 10.5f;
}
return false;
}
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
return true;
tutorialTimer = 30.5f;
}
break;
case 3: // Objective: Travel ~150 meters and while sub is not flooding [Text]
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 8000f || IsFlooding())
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 12000f || IsFlooding())
{
return false;
}
@@ -456,11 +307,6 @@ namespace Barotrauma.Tutorials
{
return false;
}
else if (floodTutorialTimer < floodTutorialDelay)
{
floodTutorialTimer += deltaTime;
return false;
}
break;
case 5: // Reactor: Player uses reactor for the first time [Video]
if (Character.Controlled?.SelectedConstruction != reactor.Item)
@@ -475,23 +321,19 @@ namespace Barotrauma.Tutorials
}
break;
case 7: // Degrading1: Any equipment degrades to 50% health or less and player has not assigned any crew to perform maintenance [Text]
if ((mechanic == null || mechanic.IsDead) && (engineer == null || engineer.IsDead)) // Both engineer and mechanic are dead or do not exist -> do not display
{
return false;
}
bool degradedEquipmentFound = false;
foreach (Item item in Item.ItemList)
{
if (!item.Repairables.Any() || item.Condition > 50.0f) continue;
if (!item.Repairables.Any() || item.ConditionPercentage > 50) continue;
degradedEquipmentFound = true;
break;
}
if (degradedEquipmentFound)
{
if (HasOrder("repairsystems", "jobspecific"))
degrading2ActivationCountdown = 5f;
if (HasOrder("repairsystems"))
{
segments[index].IsTriggered = true;
return false;
@@ -502,44 +344,43 @@ namespace Barotrauma.Tutorials
return false;
}
break;
case 8: // Medical: Crewmember is injured but not killed [Video]
if (injuredMember == null)
case 8: // Degrading2: 5 seconds after 'Degrading1' dismissed, and only if player has not assigned any crew to perform maintenance [Video]
if (degrading2ActivationCountdown == -1f)
{
for (int i = 0; i < crew.Count; i++)
return false;
}
else if (degrading2ActivationCountdown > 0.0f)
{
degrading2ActivationCountdown -= deltaTime;
if (HasOrder("repairsystems"))
{
Character member = crew[i];
if (member.Vitality < member.MaxVitality && !member.IsDead)
{
injuredMember = member;
break;
}
segments[index].IsTriggered = true;
}
return false;
}
else if (medicalTutorialTimer < medicalTutorialDelay)
break;
case 9: // Medical: Crewmember is injured but not killed [Video]
bool injuredFound = false;
for (int i = 0; i < crew.Count; i++)
{
medicalTutorialTimer += deltaTime;
return false;
Character member = crew[i];
if (member.Vitality < member.MaxVitality && !member.IsDead)
{
injuredFound = true;
break;
}
}
else
{
TriggerTutorialSegment(index, new string[] { injuredMember.Info.DisplayName,
(injuredMember.Info.Gender == Gender.Male) ? TextManager.Get("PronounPossessiveMale").ToLower() : TextManager.Get("PronounPossessiveFemale").ToLower() });
return true;
}
case 9: // Approach1: Destination is within ~100m [Video]
if (!injuredFound) return false;
break;
case 10: // Approach1: Destination is within ~100m [Video]
if (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 8000f)
{
return false;
}
else
{
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
return true;
}
case 10: // Approach2: Sub is docked [Text]
break;
case 11: // Approach2: Sub is docked [Text]
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
{
return false;
@@ -551,128 +392,11 @@ namespace Barotrauma.Tutorials
return true;
}
private bool HasObjective(string objectiveName)
{
for (int i = 0; i < activeObjectives.Count; i++)
{
if (activeObjectives[i].Id == objectiveName) return true;
}
return false;
}
private void CheckActiveObjectives(TutorialSegment objective, float deltaTime)
{
switch(objective.Id)
{
case "ReactorCommand": // Reactor commanded
if (!IsReactorPoweredUp())
{
if (!HasOrder("operatereactor")) return;
}
break;
case "NavConsole": // traveled 50 meters
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 4000f)
{
return;
}
break;
case "Flood": // Hull breaches repaired
if (IsFlooding()) return;
break;
case "Medical":
if (injuredMember != null && !injuredMember.IsDead)
{
if (injuredMember.CharacterHealth.DroppedItem == null) return;
}
break;
case "EnemyOnSonar": // Enemy dispatched
if (HasEnemyOnSonarForDuration(deltaTime))
{
return;
}
break;
case "Degrading": // Fixed
if (mechanic != null && !mechanic.IsDead)
{
HumanAIController humanAI = mechanic.AIController as HumanAIController;
if (mechanic.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
{
return;
}
}
if (engineer != null && !engineer.IsDead)
{
HumanAIController humanAI = engineer.AIController as HumanAIController;
if (engineer.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
{
return;
}
}
break;
case "Approach1": // Wait until docked
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
{
return;
}
break;
}
RemoveCompletedObjective(objective);
}
private bool IsReactorPoweredUp()
{
float load = 0.0f;
List<Connection> connections = reactor.Item.Connections;
if (connections != null && connections.Count > 0)
{
foreach (Connection connection in connections)
{
if (!connection.IsPower) continue;
foreach (Connection recipient in connection.Recipients)
{
if (!(recipient.Item is Item it)) continue;
PowerTransfer pt = it.GetComponent<PowerTransfer>();
if (pt == null) continue;
load = Math.Max(load, pt.PowerLoad);
}
}
}
return Math.Abs(load + reactor.CurrPowerConsumption) < 10;
}
private Character CrewMemberWithJob(string job)
private bool HasOrder(string aiTag)
{
for (int i = 0; i < crew.Count; i++)
{
if (crew[i].Info.Job.Name == job) return crew[i];
}
return null;
}
private bool HasOrder(string aiTag, string option = null)
{
for (int i = 0; i < crew.Count; i++)
{
if (crew[i].CurrentOrder?.AITag == aiTag)
{
if (option == null)
{
return true;
}
else
{
HumanAIController humanAI = crew[i].AIController as HumanAIController;
return humanAI.CurrentOrderOption == option;
}
}
if (crew[i].CurrentOrder?.AITag == aiTag) return true;
}
return false;
@@ -723,51 +447,27 @@ namespace Barotrauma.Tutorials
}
}
return characterTimeOnSonar.Find(ct => ct.Second >= requiredTimeOnSonar && !ct.First.IsDead) != null;
return characterTimeOnSonar.Find(ct => ct.Second >= requiredTimeOnSonar) != null;
}
private void TriggerTutorialSegment(int index, params object[] args)
{
Inventory.draggingItem = null;
ContentRunning = true;
activeSegment = segments[index];
string tutorialText = TextManager.GetFormatted(activeSegment.TextContent.GetAttributeString("tag", ""), true, args);
string objectiveText = string.Empty;
if (!string.IsNullOrEmpty(activeSegment.Objective))
{
if (args.Length == 0)
{
objectiveText = activeSegment.Objective;
}
else
{
objectiveText = string.Format(activeSegment.Objective, args);
}
activeSegment.Objective = objectiveText;
}
else
{
activeSegment.IsTriggered = true; // Complete at this stage only if no related objective
}
activeSegment.IsTriggered = true;
switch (activeSegment.ContentType)
{
case ContentTypes.None:
break;
case ContentTypes.Video:
infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Id), tutorialText,
activeSegment.TextContent.GetAttributeInt("width", 300),
activeSegment.TextContent.GetAttributeInt("height", 80),
activeSegment.TextContent.GetAttributeString("anchor", "Center"), true, ClosePreTextAndTriggerVideoCallback);
spriteSheetPlayer.LoadContent(playableContentPath, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback);
break;
case ContentTypes.TextOnly:
infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Id), tutorialText,
activeSegment.TextContent.GetAttributeInt("width", 300),
activeSegment.TextContent.GetAttributeInt("height", 80),
activeSegment.TextContent.GetAttributeString("anchor", "Center"), true, CurrentSegmentStopCallback);
case ContentTypes.Text:
infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Name), TextManager.GetFormatted(activeSegment.Content.GetAttributeString("tag", ""), false, args),
activeSegment.Content.GetAttributeInt("width", 300),
activeSegment.Content.GetAttributeInt("height", 80),
activeSegment.Content.GetAttributeString("anchor", "Center"), true, CurrentSegmentStopCallback);
break;
}
@@ -779,13 +479,6 @@ namespace Barotrauma.Tutorials
CoroutineManager.StartCoroutine(WaitToStop()); // Completed
}
private void ReplaySegmentVideo(TutorialSegment segment)
{
if (ContentRunning) return;
ContentRunning = true;
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, () => ContentRunning = false);
}
private IEnumerable<object> WaitToStop()
{
while (ContentRunning) yield return null;

View File

@@ -121,7 +121,7 @@ namespace Barotrauma.Tutorials
public virtual void AddToGUIUpdateList()
{
if (infoBox != null) infoBox.AddToGUIUpdateList(order: 100);
if (infoBox != null) infoBox.AddToGUIUpdateList();
}
public virtual void Update(float deltaTime)
@@ -194,7 +194,7 @@ namespace Barotrauma.Tutorials
if (title.Length > 0)
{
var titleBlock = new GUITextBlock(new RectTransform(new Vector2(1f, .35f), infoBlock.RectTransform, Anchor.TopCenter,
Pivot.TopCenter), title, font: GUI.VideoTitleFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0));
Pivot.TopCenter), title, font: GUI.LargeFont, textAlignment: Alignment.Center);
}
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.9f, 1f), infoBlock.RectTransform, Anchor.BottomCenter),

View File

@@ -127,6 +127,18 @@ namespace Barotrauma.Items.Components
Stretch = true,
RelativeSpacing = 0.03f
};
autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform),
TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton")
{
OnSelected = (GUITickBox box) =>
{
AutoPilot = box.Selected;
if (AutoPilot && MaintainPos)
{
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
}
unsentChanges = true;
user = Character.Controlled;
maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform),
TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont)
@@ -484,26 +496,14 @@ namespace Barotrauma.Items.Components
user = Character.Controlled;
}
}
if (!AutoPilot && Character.DisableControls)
if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
{
steeringAdjustSpeed = character == null ? 0.2f : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
Vector2 input = Vector2.Zero;
if (PlayerInput.KeyDown(InputType.Left))
{
input -= Vector2.UnitX;
}
if (PlayerInput.KeyDown(InputType.Right))
{
input += Vector2.UnitX;
}
if (PlayerInput.KeyDown(InputType.Up))
{
input += Vector2.UnitY;
}
if (PlayerInput.KeyDown(InputType.Down))
{
input -= Vector2.UnitY;
}
if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
if (PlayerInput.KeyDown(InputType.Up)) { input += Vector2.UnitY; }
if (PlayerInput.KeyDown(InputType.Down)) { input -= Vector2.UnitY; }
if (PlayerInput.KeyDown(Keys.LeftShift))
{
SteeringInput += input * deltaTime * 200;

View File

@@ -364,15 +364,23 @@ namespace Barotrauma
}
}
if (GUI.KeyboardDispatcher.Subscriber == null)
{
float moveSpeed = 1000.0f;
Vector2 moveAmount = Vector2.Zero;
if (PlayerInput.KeyDown(InputType.Left)) { moveAmount += Vector2.UnitX; }
if (PlayerInput.KeyDown(InputType.Right)) { moveAmount -= Vector2.UnitX; }
if (PlayerInput.KeyDown(InputType.Up)) { moveAmount += Vector2.UnitY; }
if (PlayerInput.KeyDown(InputType.Down)) { moveAmount -= Vector2.UnitY; }
drawOffset += moveAmount * moveSpeed / zoom * deltaTime;
}
if (GUI.MouseOn == mapContainer)
{
zoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
zoom = MathHelper.Clamp(zoom, 1.0f, 4.0f);
if (PlayerInput.MidButtonHeld())
{
drawOffset += PlayerInput.MouseSpeed / zoom;
}
if (PlayerInput.MidButtonHeld()) { drawOffset += PlayerInput.MouseSpeed / zoom; }
#if DEBUG
if (PlayerInput.DoubleClicked() && highlightedLocation != null)
{
@@ -551,11 +559,6 @@ namespace Barotrauma
null, connectionColor * MathHelper.Clamp(a, 0.1f, 0.5f), MathUtils.VectorToAngle(end - start),
new Vector2(0, 16), SpriteEffects.None, 0.01f);
}
}
rect.Inflate(8, 8);
GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8);
GUI.DrawRectangle(spriteBatch, rect, Color.LightGray);
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
{

View File

@@ -292,8 +292,7 @@ namespace Barotrauma
{
if (damageEffect != null)
{
float newCutoff = Sections[i].damage > 0 ?
MathHelper.Lerp(0.2f, 0.65f, Sections[i].damage / Prefab.Health) : 0.0f;
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / Prefab.Health);
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
{

View File

@@ -141,8 +141,23 @@ namespace Barotrauma.Networking
{
OnClicked = (btn, userdata) =>
{
if (!permissions.HasFlag(ClientPermissions.ManageRound)) return false;
RequestRoundEnd();
if (!permissions.HasFlag(ClientPermissions.ManageRound)) { return false; }
if (!Submarine.MainSub.AtStartPosition && !Submarine.MainSub.AtEndPosition)
{
var msgBox = new GUIMessageBox("", TextManager.Get("EndRoundSubNotAtLevelEnd"),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
msgBox.Buttons[0].OnClicked = (_, __) =>
{
GameMain.Client.RequestRoundEnd();
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked += msgBox.Close;
}
else
{
RequestRoundEnd();
}
return true;
},
Visible = false
@@ -1267,6 +1282,75 @@ namespace Barotrauma.Networking
}
}
private void ReadLobbyUpdate(NetIncomingMessage inc)
{
UInt16 listId = inc.ReadUInt16();
List<TempClient> tempClients = new List<TempClient>();
int clientCount = inc.ReadByte();
for (int i = 0; i < clientCount; i++)
{
byte id = inc.ReadByte();
string name = inc.ReadString();
UInt16 characterID = inc.ReadUInt16();
bool muted = inc.ReadBoolean();
inc.ReadPadBits();
tempClients.Add(new TempClient
{
ID = id,
Name = name,
CharacterID = characterID,
Muted = muted
});
}
if (NetIdUtils.IdMoreRecent(listId, LastClientListUpdateID))
{
bool updateClientListId = true;
List<Client> currentClients = new List<Client>();
foreach (TempClient tc in tempClients)
{
//see if the client already exists
var existingClient = ConnectedClients.Find(c => c.ID == tc.ID && c.Name == tc.Name);
if (existingClient == null) //if not, create it
{
existingClient = new Client(tc.Name, tc.ID)
{
Muted = tc.Muted
};
ConnectedClients.Add(existingClient);
GameMain.NetLobbyScreen.AddPlayer(existingClient);
}
existingClient.Character = null;
existingClient.Muted = tc.Muted;
if (tc.CharacterID > 0)
{
existingClient.Character = Entity.FindEntityByID(tc.CharacterID) as Character;
if (existingClient.Character == null)
{
updateClientListId = false;
}
}
if (existingClient.ID == myID)
{
existingClient.SetPermissions(permissions, permittedConsoleCommands);
}
currentClients.Add(existingClient);
}
//remove clients that aren't present anymore
for (int i = ConnectedClients.Count - 1; i >= 0; i--)
{
if (!currentClients.Contains(ConnectedClients[i]))
{
GameMain.NetLobbyScreen.RemovePlayer(ConnectedClients[i]);
ConnectedClients[i].Dispose();
ConnectedClients.RemoveAt(i);
}
}
if (updateClientListId) LastClientListUpdateID = listId;
}
}
private void ReadLobbyUpdate(NetIncomingMessage inc)
{
ServerNetObject objHeader;
@@ -1377,114 +1461,6 @@ namespace Barotrauma.Networking
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CLIENT_LIST:
ReadClientList(inc);
break;
case ServerNetObject.CHAT_MESSAGE:
ChatMessage.ClientRead(inc);
break;

View File

@@ -64,14 +64,11 @@ namespace Barotrauma
// New game left side
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), leftColumn.RectTransform), TextManager.Get("SelectedSub") + ":", textAlignment: Alignment.BottomLeft);
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform))
{
OnSelected = CheckForPax
};
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform));
UpdateSubList(submarines);
// New game right sideon
// New game right side
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), TextManager.Get("SaveName") + ":", textAlignment: Alignment.BottomLeft);
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), string.Empty);
@@ -271,11 +268,6 @@ namespace Barotrauma
saveFiles = SaveUtil.GetSaveFiles(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
}
saveList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform, Anchor.CenterLeft))
{
OnSelected = SelectSaveFile
};
saveList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform, Anchor.CenterLeft))
{
OnSelected = SelectSaveFile
@@ -283,7 +275,9 @@ namespace Barotrauma
foreach (string saveFile in saveFiles)
{
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
string fileName = saveFile;
string subName = "";
string saveTime = "";
var saveFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), saveList.Content.RectTransform), style: "ListBoxElement")
{
UserData = saveFile
@@ -291,25 +285,38 @@ namespace Barotrauma
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform),
text: Path.GetFileNameWithoutExtension(saveFile));
if (doc?.Root == null)
{
DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
nameText.Color = Color.Red;
continue;
}
string submarineName = doc.Root.GetAttributeString("submarine", "");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
text: submarineName, font: GUI.SmallFont)
if (!isMultiplayer)
{
UserData = saveFile
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
if (doc?.Root == null)
{
DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
nameText.Color = Color.Red;
continue;
}
subName = doc.Root.GetAttributeString("submarine", "");
saveTime = doc.Root.GetAttributeString("savetime", "");
}
else
{
string[] splitSaveFile = saveFile.Split(';');
saveFrame.UserData = splitSaveFile[0];
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
}
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
text: subName, font: GUI.SmallFont)
{
UserData = fileName
};
string saveTime = doc.Root.GetAttributeString("savetime", "");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), saveFrame.RectTransform),
text: saveTime, textAlignment: Alignment.Right, font: GUI.SmallFont)
{
UserData = saveFile
UserData = fileName
};
}
@@ -358,25 +365,7 @@ namespace Barotrauma
{
if (isMultiplayer) return;
Tutorial contextualTutorial = Tutorial.Tutorials.Find(t => t is ContextualTutorial);
Submarine selectedSub = subList.SelectedData as Submarine;
if (selectedSub == null || selectedSub.Name != "PAX")
{
contextualTutorialBox.Selected = (contextualTutorial != null) ? !GameMain.Config.CompletedTutorialNames.Contains(contextualTutorial.Name) : true;
}
else
{
contextualTutorialBox.Selected = true;
}
}
private bool CheckForPax(GUIComponent component, object obj)
{
if (!(obj is Submarine) || contextualTutorialBox == null) return false;
Submarine sub = obj as Submarine;
contextualTutorialBox.Selected = sub.Name == "PAX";
return true;
contextualTutorialBox.Selected = (contextualTutorial != null) ? !GameMain.Config.CompletedTutorialNames.Contains(contextualTutorial.Name) : true;
}
private bool SelectSaveFile(GUIComponent component, object obj)

View File

@@ -118,6 +118,19 @@ namespace Barotrauma
instance = this;
}
private void Reset()
{
AnimParams.ForEach(a => a.Reset(true));
RagdollParams.Reset(true);
RagdollParams.ClearHistory();
CurrentAnimation.ClearHistory();
if (!character.Removed)
{
character.Remove();
}
character = null;
}
public override void Deselect()
{
base.Deselect();
@@ -128,15 +141,7 @@ namespace Barotrauma
isEndlessRunner = false;
if (character != null)
{
AnimParams.ForEach(a => a.Reset(true));
RagdollParams.Reset(true);
RagdollParams.ClearHistory();
CurrentAnimation.ClearHistory();
if (!character.Removed)
{
character.Remove();
}
character = null;
Reset();
}
GameMain.World.ProcessChanges();
}
@@ -393,6 +398,12 @@ namespace Barotrauma
}
if (!isFreezed)
{
if (character.AnimController.Invalid)
{
Reset();
SpawnCharacter(currentCharacterConfig);
}
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
Submarine.MainSub.Update((float)deltaTime);
@@ -1215,7 +1226,7 @@ namespace Barotrauma
Cam.Position = character.WorldPosition;
}
private bool CreateCharacter(string name, bool isHumanoid, params object[] ragdollConfig)
private bool CreateCharacter(string name, string mainFolder, bool isHumanoid, params object[] ragdollConfig)
{
var contentPackage = GameMain.Config.SelectedContentPackages.LastOrDefault();
if (contentPackage == null)
@@ -1234,17 +1245,16 @@ namespace Barotrauma
#endif
string speciesName = name;
string mainFolder = $"Content/Characters/{speciesName}";
// Config file
string configFilePath = $"{mainFolder}/{speciesName}.xml";
string configFilePath = Path.Combine(mainFolder, $"{speciesName}.xml").Replace(@"\", @"/");
if (ContentPackage.GetFilesOfType(GameMain.SelectedPackages, ContentType.Character).None(path => path.Contains(speciesName)))
{
// Create the config file
XElement mainElement = new XElement("Character",
new XAttribute("name", speciesName),
new XAttribute("humanoid", isHumanoid),
new XElement("ragdolls"),
new XElement("animations"),
new XElement("ragdolls", new XAttribute("folder", Path.Combine(mainFolder, $"Ragdolls/").Replace(@"\", @"/"))),
new XElement("animations", new XAttribute("folder", Path.Combine(mainFolder, $"Animations/").Replace(@"\", @"/"))),
new XElement("health"),
new XElement("ai"));
XDocument doc = new XDocument(mainElement);
@@ -1259,13 +1269,13 @@ namespace Barotrauma
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
}
// Ragdoll
string ragdollFolder = RagdollParams.GetDefaultFolder(speciesName);
string ragdollFolder = RagdollParams.GetFolder(speciesName);
string ragdollPath = RagdollParams.GetDefaultFile(speciesName);
RagdollParams ragdollParams = isHumanoid
? RagdollParams.CreateDefault<HumanRagdollParams>(ragdollPath, speciesName, ragdollConfig)
: RagdollParams.CreateDefault<FishRagdollParams>(ragdollPath, speciesName, ragdollConfig) as RagdollParams;
// Animations
string animFolder = AnimationParams.GetDefaultFolder(speciesName);
string animFolder = AnimationParams.GetFolder(speciesName);
foreach (AnimationType animType in Enum.GetValues(typeof(AnimationType)))
{
if (animType != AnimationType.NotDefined)
@@ -3918,7 +3928,7 @@ namespace Barotrauma
private void DrawJointLimitWidgets(SpriteBatch spriteBatch, Limb limb, LimbJoint joint, Vector2 drawPos, bool autoFreeze, bool allowPairEditing, float rotationOffset = 0)
{
rotationOffset -= MathHelper.ToRadians(RagdollParams.SpritesheetOrientation);
rotationOffset += MathHelper.ToRadians(RagdollParams.SpritesheetOrientation);
Color angleColor = joint.UpperLimit - joint.LowerLimit > 0 ? Color.LightGreen * 0.5f : Color.Red;
DrawRadialWidget(spriteBatch, drawPos, MathHelper.ToDegrees(joint.UpperLimit), $"joint.jointParams.Name {GetCharacterEditorTranslation("UpperLimit")}", Color.Cyan, angle =>
{
@@ -4652,7 +4662,7 @@ namespace Barotrauma
LimbXElements.Values,
JointXElements
};
if (CharacterEditorScreen.instance.CreateCharacter(Name, IsHumanoid, ragdollParams))
if (CharacterEditorScreen.instance.CreateCharacter(Name, Path.GetDirectoryName(XMLPath), IsHumanoid, ragdollParams))
{
GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", Name), Color.Green, font: GUI.Font);
}

View File

@@ -866,18 +866,21 @@ namespace Barotrauma
spectateButton.Enabled = true;
}
public void SetCampaignCharacterInfo(CharacterInfo characterInfo)
{
if (CampaignCharacterDiscarded) return;
campaignCharacterInfo = characterInfo;
if (campaignCharacterInfo != null)
public void SetCampaignCharacterInfo(CharacterInfo newCampaignCharacterInfo)
{
if (newCampaignCharacterInfo != null)
{
UpdatePlayerFrame(campaignCharacterInfo, false);
if (CampaignCharacterDiscarded) { return; }
if (campaignCharacterInfo != newCampaignCharacterInfo)
{
campaignCharacterInfo = newCampaignCharacterInfo;
UpdatePlayerFrame(campaignCharacterInfo, false);
}
}
else
else if (campaignCharacterInfo != null)
{
UpdatePlayerFrame(null, true);
campaignCharacterInfo = null;
UpdatePlayerFrame(campaignCharacterInfo, false);
}
}

View File

@@ -564,6 +564,9 @@ namespace Barotrauma
MapEntityPrefab.Selected = null;
saveFrame = null;
loadFrame = null;
MapEntity.DeselectAll();
MapEntity.SelectionGroups.Clear();
@@ -2040,6 +2043,10 @@ namespace Barotrauma
dummyCharacter.SelectedConstruction = null;
}
}
else if (MapEntity.SelectedList.Count == 1)
{
(MapEntity.SelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
}
CharacterHUD.Update((float)deltaTime, dummyCharacter, cam);
}

View File

@@ -10,6 +10,7 @@ using System.Text;
using System.IO.Compression;
using System.IO;
using Barotrauma.Steam;
using System.Xml.Linq;
namespace Barotrauma.Networking
{
@@ -1039,7 +1040,7 @@ namespace Barotrauma.Networking
if (command == ClientPermissions.ManageRound && inc.PeekBoolean() &&
GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign)
{
if (!mpCampaign.AllowedToEndRound(sender.Character))
if (!mpCampaign.AllowedToEndRound(sender.Character) && !sender.HasPermission(command))
{
return;
}
@@ -1125,9 +1126,22 @@ namespace Barotrauma.Networking
UInt16 modeIndex = inc.ReadUInt16();
if (GameMain.NetLobbyScreen.GameModes[modeIndex].Identifier.ToLowerInvariant() == "multiplayercampaign")
{
string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
for (int i = 0; i < saveFiles.Length; i++)
{
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFiles[i]);
if (doc?.Root != null)
{
saveFiles[i] =
string.Join(";",
saveFiles[i].Replace(';', ' '),
doc.Root.GetAttributeString("submarine", ""),
doc.Root.GetAttributeString("savetime", ""));
}
}
NetOutgoingMessage msg = server.CreateMessage();
msg.Write((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
msg.Write((UInt16)saveFiles.Count());
foreach (string saveFile in saveFiles)
{
@@ -1212,6 +1226,7 @@ namespace Barotrauma.Networking
ClientWriteLobby(c);
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign &&
GameMain.NetLobbyScreen.SelectedMode == campaign.Preset &&
NetIdUtils.IdMoreRecent(campaign.LastSaveID, c.LastRecvCampaignSave))
{
//already sent an up-to-date campaign save
@@ -1529,7 +1544,8 @@ namespace Barotrauma.Networking
}
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
if (campaign != null && NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
if (campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode &&
NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
{
outmsg.Write(true);
outmsg.WritePadBits();

View File

@@ -332,7 +332,7 @@ namespace Barotrauma.Networking
}
}
if (client.NeedsMidRoundSync)
foreach (NetEntityEvent entityEvent in sentEvents)
{
msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
msg.Write(client.UnreceivedEntityEventCount);
@@ -340,36 +340,13 @@ namespace Barotrauma.Networking
Write(msg, eventsToSync, out sentEvents, client);
}
else
foreach (NetEntityEvent entityEvent in sentEvents)
{
msg.Write((byte)ServerNetObject.ENTITY_EVENT);
Write(msg, eventsToSync, out sentEvents, client);
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;

View File

@@ -56,6 +56,7 @@
<Character file="Content/Characters/Husk/Husk.xml" />
<Character file="Content/Characters/Humanhusk/Humanhusk.xml" />
<Character file="Content/Characters/Legacyhusk/Legacyhusk.xml" />
<Character file="Content/Characters/Legacycharybdis/Legacycharybdis.xml" />
<Character file="Content/Characters/Legacycrawler/Legacycrawler.xml" />
<Character file="Content/Characters/Legacymoloch/Legacymoloch.xml" />
<Character file="Content/Characters/Mudraptor/Mudraptor.xml" />
@@ -70,7 +71,7 @@
<Outpost file="Content/Map/Outposts/Outpost.sub" />
<Submarine file="Submarines/Orca.sub" />
<Submarine file="Submarines/Typhon.sub" />
<Submarine file="Submarines/Muikku.sub" />
<Submarine file="Submarines/Selkie.sub" />
<Submarine file="Submarines/Bunyip.sub" />
<Submarine file="Submarines/Humpback.sub" />
<Submarine file="Submarines/Dugong.sub" />

View File

@@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Carrier\Animations\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Animations\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Coelanth\Animations\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycrawler\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Endworm\Animations\" />
@@ -45,12 +45,27 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Carrier\Ragdolls\CarrierDefaultRagdoll.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Animations\CharybdisSwimFast.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Animations\CharybdisSwimSlow.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Charybdis.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Charybdis.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Ragdolls\CharybdisDefaultRagdoll.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\Legacycharybdis.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\Ragdolls\LegacycharybdisDefaultRagdoll.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Coelanth\Coelanth.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -342,33 +357,6 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Effects\waterbump.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\1_CommandReactor\BaroTutorial_CommandReactor.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\BaroTutorial_NavConsole.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\BaroTutorial_Flood.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\BaroTutorial_Reactor.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\5_EnemyOnSonar\BaroTutorial_EnemyOnSonar.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\6_Degrading2\BaroTutorial_Degrading.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\BaroTutorial_Medical.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\BaroTutorial_Approach.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="$(MSBuildThisFileDirectory)Content\Fonts\BebasNeue-Regular.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Content Include="$(MSBuildThisFileDirectory)Content\Fonts\NotoSans\LICENSE_OFL.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -924,13 +912,13 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Carrier\Animations\CarrierSwimSlow.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\charybdis.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\charybdis.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Animations\CharybdisSwimFast.xml">
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\Animations\LegacycharybdisSwimFast.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\Animations\CharybdisSwimSlow.xml">
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\Animations\LegacycharybdisSwimSlow.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Characters\Coelanth\Animations\CoelanthSwimFast.xml">
@@ -2383,7 +2371,7 @@
<None Include="$(MSBuildThisFileDirectory)Content\Characters\Mudraptor\MUDRAPTOR_idle3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Characters\Charybdis\charybdisattack.ogg">
<None Include="$(MSBuildThisFileDirectory)Content\Characters\Legacycharybdis\charybdisattack.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Characters\Coelanth\attack1.ogg">
@@ -3141,7 +3129,7 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Muikku.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Orca.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -3161,6 +3149,9 @@
<None Include="$(MSBuildThisFileDirectory)Submarines\RemoraDrone.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Selkie.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Typhon.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@@ -288,7 +288,7 @@ namespace Barotrauma
}
else
{
var targetingPriority = UpdateTargets(Character);
UpdateTargets(Character, out TargetingPriority targetingPriority);
updateTargetsTimer = UpdateTargetsInterval;
if (SelectedAiTarget == null)
@@ -472,7 +472,10 @@ namespace Barotrauma
}
else
{
UpdateWallTarget();
if (!IsProperlyLatched)
{
UpdateWallTarget();
}
raycastTimer = RaycastInterval;
}
@@ -496,6 +499,10 @@ namespace Barotrauma
if (wallTarget != null)
{
attackWorldPos = wallTarget.Position;
if (wallTarget.Structure.Submarine != null)
{
attackWorldPos += wallTarget.Structure.Submarine.Position;
}
attackSimPos = ConvertUnits.ToSimUnits(attackWorldPos);
}
else
@@ -840,12 +847,7 @@ namespace Barotrauma
attachTargetNormal = new Vector2(Math.Sign(WorldPosition.X - wall.WorldPosition.X), 0.0f);
sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X;
}
latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, sectionPos, attachTargetNormal);
if (wall.Submarine != null)
{
sectionPos += wall.Submarine.Position;
}
latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal);
wallTarget = new WallTarget(sectionPos, wall, sectionIndex);
}
}
@@ -978,10 +980,17 @@ namespace Barotrauma
//goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range
public TargetingPriority UpdateTargets(Character character)
public AITarget UpdateTargets(Character character, out TargetingPriority priority)
{
if (IsProperlyLatched)
{
// If attached to a valid target, just keep the target.
// Priority not used in this case.
priority = null;
return SelectedAiTarget;
}
AITarget newTarget = null;
TargetingPriority targetingPriority = null;
priority = null;
selectedTargetMemory = null;
targetValue = 0.0f;
@@ -1180,7 +1189,7 @@ namespace Barotrauma
{
newTarget = target;
selectedTargetMemory = targetMemory;
targetingPriority = targetingPriorities[targetingTag];
priority = targetingPriorities[targetingTag];
targetValue = valueModifier;
}
}
@@ -1190,7 +1199,7 @@ namespace Barotrauma
{
wallTarget = null;
}
return targetingPriority;
return SelectedAiTarget;
}
private AITargetMemory GetTargetMemory(AITarget target)

View File

@@ -193,7 +193,7 @@ namespace Barotrauma
// is not attached or is attached to something else
if (!IsAttached || IsAttached && attachJoints[0].BodyB == attachTargetBody)
{
if (Vector2.DistanceSquared(ConvertUnits.ToDisplayUnits(transformedAttachPos), enemyAI.AttackingLimb.WorldPosition) < enemyAI.AttackingLimb.attack.Range * enemyAI.AttackingLimb.attack.Range)
if (Vector2.DistanceSquared(ConvertUnits.ToDisplayUnits(transformedAttachPos), enemyAI.AttackingLimb.WorldPosition) < enemyAI.AttackingLimb.attack.DamageRange * enemyAI.AttackingLimb.attack.DamageRange)
{
AttachToBody(character.AnimController.Collider, attachLimb, attachTargetBody, transformedAttachPos);
}

View File

@@ -369,7 +369,16 @@ namespace Barotrauma
float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2;
float mainLimbAngle = (MainLimb.type == LimbType.Torso ? TorsoAngle.Value : HeadAngle.Value) * Dir;
float mainLimbAngle = 0;
if (MainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
{
mainLimbAngle = TorsoAngle.Value;
}
else if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
{
mainLimbAngle = HeadAngle.Value;
}
mainLimbAngle *= Dir;
while (MainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
{
movementAngle += MathHelper.TwoPi;
@@ -408,7 +417,7 @@ namespace Barotrauma
}
}
}
while (MainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi)
else
{
movementAngle = Dir > 0 ? -MathHelper.PiOver2 : MathHelper.PiOver2;
if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
@@ -683,12 +692,6 @@ namespace Barotrauma
limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength);
}
while (referenceLimb.Rotation - angle < -MathHelper.TwoPi)
{
angle -= MathHelper.TwoPi;
}
limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
}
private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque)

View File

@@ -99,7 +99,7 @@ namespace Barotrauma
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Animations/";
public static string GetDefaultFile(string speciesName, AnimationType animType) => $"{GetFolder(speciesName)}{GetDefaultFileName(speciesName, animType)}.xml";
protected static string GetFolder(string speciesName)
public static string GetFolder(string speciesName)
{
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName))?.Root?.Element("animations")?.GetAttributeString("folder", string.Empty);
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")

View File

@@ -79,7 +79,7 @@ namespace Barotrauma
new XAttribute("sourcerect", $"0, 0, 1, 1")))
};
protected static string GetFolder(string speciesName)
public static string GetFolder(string speciesName)
{
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName))?.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")

View File

@@ -1035,78 +1035,6 @@ namespace Barotrauma
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
CheckValidity();
UpdateNetPlayerPosition(deltaTime);
CheckDistFromCollider();
UpdateCollisionCategories();
@@ -1367,17 +1295,42 @@ namespace Barotrauma
UpdateProjSpecific(deltaTime);
}
private void CheckValidity()
public bool Invalid { get; private set; }
private int validityResets;
private bool CheckValidity()
{
CheckValidity(Collider);
bool isColliderValid = CheckValidity(Collider);
bool limbsValid = true;
foreach (Limb limb in limbs)
{
if (limb.body == null || !limb.body.Enabled) { continue; }
CheckValidity(limb.body);
if (!CheckValidity(limb.body))
{
limbsValid = false;
break;
}
}
bool isValid = isColliderValid && limbsValid;
if (!isValid)
{
validityResets++;
if (validityResets > 1)
{
Invalid = true;
DebugConsole.ThrowError("Invalid ragdoll physics. Ragdoll freezed to prevent crashes.");
Collider.SetTransform(Vector2.Zero, 0.0f);
foreach (Limb limb in Limbs)
{
limb.body.SetTransform(Collider.SimPosition, 0.0f);
limb.body.ResetDynamics();
}
Frozen = true;
}
}
return isValid;
}
private void CheckValidity(PhysicsBody body)
private bool CheckValidity(PhysicsBody body)
{
string errorMsg = null;
string bodyName = body.UserData is Limb ? "Limb" : "Collider";
@@ -1429,9 +1382,9 @@ namespace Barotrauma
limb.body.ResetDynamics();
}
SetInitialLimbPositions();
return;
return false;
}
UpdateProjSpecific(deltaTime);
return true;
}
partial void UpdateProjSpecific(float deltaTime);

View File

@@ -808,6 +808,7 @@ namespace Barotrauma
public void LoadHeadAttachments()
{
if (Info == null) { return; }
if (AnimController == null) { return; }
var head = AnimController.GetLimb(LimbType.Head);
if (head == null) { return; }

View File

@@ -804,6 +804,11 @@ namespace Barotrauma
var newItem = Item.Load(itemElement, inventory.Owner.Submarine, createNetworkEvent: true);
if (newItem == null) { continue; }
if (!MathUtils.NearlyEqual(newItem.Condition, newItem.MaxCondition))
{
GameMain.NetworkMember.CreateEntityEvent(newItem, new object[] { NetEntityEvent.Type.Status });
}
int[] slotIndices = itemElement.GetAttributeIntArray("i", new int[] { 0 });
if (!slotIndices.Any())
{

View File

@@ -528,7 +528,7 @@ namespace Barotrauma
}
else
{
// If the attack is aimed to a character but hits a structure, the hit is blocked.
// If there is nothing between, the hit is successful
wasHit = structureBody == null;
}
}

View File

@@ -118,8 +118,13 @@ namespace Barotrauma
{
allowedMissions.RemoveAll(m => !m.IsAllowed(locations[0], locations[1]));
}
if (allowedMissions.Count == 0)
{
return null;
}
int probabilitySum = allowedMissions.Sum(m => m.Commonness);
int probabilitySum = allowedMissions.Sum(m => m.Commonness);
int randomNumber = rand.NextInt32() % probabilitySum;
foreach (MissionPrefab missionPrefab in allowedMissions)
{

View File

@@ -534,7 +534,6 @@ namespace Barotrauma.Items.Components
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return 0.0f;
}
float average = skillSuccessSum / requiredSkills.Count;
float skillSuccessSum = 0.0f;
for (int i = 0; i < requiredSkills.Count; i++)

View File

@@ -153,7 +153,7 @@ namespace Barotrauma.Items.Components
}
continue;
}
if (!pt.IsActive) { continue; }
if (!pt.IsActive || !pt.CanTransfer) { continue; }
gridLoad += pt.PowerLoad;
gridPower -= pt.CurrPowerConsumption;
@@ -209,9 +209,9 @@ namespace Barotrauma.Items.Components
Charge -= CurrPowerOutput / 3600.0f;
}
item.SendSignal(0, Charge.ToString(), "charge", null);
item.SendSignal(0, ((Charge / capacity) * 100).ToString(), "charge_%", null);
item.SendSignal(0, ((RechargeSpeed / maxRechargeSpeed) * 100).ToString(), "charge_rate", null);
item.SendSignal(0, ((int)Charge).ToString(), "charge", null);
item.SendSignal(0, ((int)((Charge / capacity) * 100)).ToString(), "charge_%", null);
item.SendSignal(0, ((int)((RechargeSpeed / maxRechargeSpeed) * 100)).ToString(), "charge_rate", null);
foreach (Pair<Powered, Connection> connected in directlyConnected)
{

View File

@@ -319,7 +319,13 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
float maxPower = this is RelayComponent relayComponent ? relayComponent.MaxPower : float.PositiveInfinity;
//float maxPower = this is RelayComponent relayComponent ? relayComponent.MaxPower : float.PositiveInfinity;
RelayComponent thisRelayComponent = this as RelayComponent;
if (thisRelayComponent != null)
{
clampPower = Math.Min(Math.Min(clampPower, thisRelayComponent.MaxPower), powerLoad);
clampLoad = Math.Min(clampLoad, thisRelayComponent.MaxPower);
}
foreach (Connection c in PowerConnections)
{
@@ -357,6 +363,8 @@ namespace Barotrauma.Items.Components
continue;
}
float addLoad = 0.0f;
float addPower = 0.0f;
if (powered is PowerContainer powerContainer)
{
if (recipient.Name == "power_in")
@@ -365,7 +373,7 @@ namespace Barotrauma.Items.Components
}
else
{
fullPower += Math.Min(powerContainer.CurrPowerOutput, maxPower);
addPower = powerContainer.CurrPowerOutput;
}
}
else
@@ -380,10 +388,16 @@ namespace Barotrauma.Items.Components
//negative power consumption = the construction is a
//generator/battery or another junction box
{
fullPower -= Math.Max(powered.CurrPowerConsumption, -maxPower);
addPower -= powered.CurrPowerConsumption;
}
}
}
if (addPower + fullPower > clampPower) { addPower -= (addPower + fullPower) - clampPower; };
if (addPower > 0) { fullPower += addPower; }
if (addLoad + fullLoad > clampLoad) { addLoad -= (addLoad + fullLoad) - clampLoad; };
if (addLoad > 0) { fullLoad += addLoad; }
}
}
}
}

View File

@@ -28,8 +28,10 @@ namespace Barotrauma
public Explosion(float range, float force, float damage, float structureDamage, float empStrength = 0.0f)
{
attack = new Attack(damage, 0.0f, 0.0f, structureDamage, range);
attack.SeverLimbsProbability = 1.0f;
attack = new Attack(damage, 0.0f, 0.0f, structureDamage, range)
{
SeverLimbsProbability = 1.0f
};
this.force = force;
this.empStrength = empStrength;
sparks = true;
@@ -183,114 +185,6 @@ namespace Barotrauma
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
bool underWater = hull == null || explosionPos.Y < hull.Surface;
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
Dictionary<Limb, float> distFactors = new Dictionary<Limb, float>();

View File

@@ -323,7 +323,7 @@ namespace Barotrauma
for (int i = 0; i <= maxLoadRetries; i++)
{
doc = OpenFile(filePath);
if (doc != null || i == maxLoadRetries) { break; }
if (doc != null || i == maxLoadRetries || !File.Exists(filePath)) { break; }
DebugConsole.NewMessage("Opening submarine file \"" + filePath + "\" failed, retrying in 250 ms...");
Thread.Sleep(250);
}
@@ -1192,7 +1192,7 @@ namespace Barotrauma
for (int i = 0; i <= maxLoadRetries; i++)
{
doc = OpenFile(filePath);
if (doc != null || i == maxLoadRetries) { break; }
if (doc != null || i == maxLoadRetries || !File.Exists(filePath)) { break; }
DebugConsole.NewMessage("Loading the submarine \"" + Name + "\" failed, retrying in 250 ms...");
Thread.Sleep(250);
}

View File

@@ -358,8 +358,8 @@ namespace Barotrauma
}
catch (IOException e)
{
if (i >= maxRetries) { throw; }
DebugConsole.NewMessage("Failed to initiate a file transfer {" + e.Message + "}, retrying in 250 ms...", Color.Red);
if (i >= maxRetries || !File.Exists(sCompressedFile)) { throw; }
DebugConsole.NewMessage("Failed decompress file \"" + sCompressedFile + "\" {" + e.Message + "}, retrying in 250 ms...", Color.Red);
Thread.Sleep(250);
}
}