(44ca39e16) Added: Escaping the video player via enter, multiple objective tracking & removing
This commit is contained in:
@@ -1485,6 +1485,195 @@ namespace Barotrauma
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
LocalizationCSVtoXML.Convert(args[0]);
|
||||||
|
}));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
commands.Add(new Command("cleanbuild", "", (string[] args) =>
|
||||||
|
{
|
||||||
|
GameMain.Config.MusicVolume = 0.5f;
|
||||||
|
GameMain.Config.SoundVolume = 0.5f;
|
||||||
|
NewMessage("Music and sound volume set to 0.5", Color.Green);
|
||||||
|
|
||||||
|
commands.Add(new Command("camerasettings", "camerasettings [defaultzoom] [zoomsmoothness] [movesmoothness] [minzoom] [maxzoom]: debug command for testing camera settings. The values default to 1.1, 8.0, 8.0, 0.1 and 2.0.", (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) =>
|
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?
|
//TODO: maybe do this automatically during loading when possible?
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Xml.Linq;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.Media;
|
using Barotrauma.Media;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -157,6 +158,14 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (PlayerInput.KeyHit(Keys.Enter))
|
||||||
|
{
|
||||||
|
DisposeVideo(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void AddToGUIUpdateList()
|
public void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (!IsPlaying()) return;
|
if (!IsPlaying()) return;
|
||||||
|
|||||||
+174
-60
@@ -26,6 +26,10 @@ namespace Barotrauma.Tutorials
|
|||||||
private Sonar sonar;
|
private Sonar sonar;
|
||||||
private Vector2 subStartingPosition;
|
private Vector2 subStartingPosition;
|
||||||
private List<Character> crew;
|
private List<Character> crew;
|
||||||
|
private Character mechanic;
|
||||||
|
private Character engineer;
|
||||||
|
private Character injuredMember = null;
|
||||||
|
|
||||||
private List<Pair<Character, float>> characterTimeOnSonar;
|
private List<Pair<Character, float>> characterTimeOnSonar;
|
||||||
private float requiredTimeOnSonar = 5f;
|
private float requiredTimeOnSonar = 5f;
|
||||||
|
|
||||||
@@ -39,7 +43,6 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
private GUIFrame holderFrame, objectiveFrame;
|
private GUIFrame holderFrame, objectiveFrame;
|
||||||
private bool objectivesOpen = false;
|
private bool objectivesOpen = false;
|
||||||
private GUITextBlock objectiveTitle, objectiveText;
|
|
||||||
private List<TutorialSegment> activeObjectives = new List<TutorialSegment>();
|
private List<TutorialSegment> activeObjectives = new List<TutorialSegment>();
|
||||||
|
|
||||||
private class TutorialSegment
|
private class TutorialSegment
|
||||||
@@ -50,6 +53,7 @@ namespace Barotrauma.Tutorials
|
|||||||
public XElement TextContent;
|
public XElement TextContent;
|
||||||
public XElement VideoContent;
|
public XElement VideoContent;
|
||||||
public bool IsTriggered;
|
public bool IsTriggered;
|
||||||
|
public GUITextBlock LinkedTitle, LinkedText;
|
||||||
|
|
||||||
public TutorialSegment(XElement config)
|
public TutorialSegment(XElement config)
|
||||||
{
|
{
|
||||||
@@ -166,6 +170,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
base.Start();
|
base.Start();
|
||||||
|
|
||||||
|
CreateObjectiveFrame();
|
||||||
activeSegment = null;
|
activeSegment = null;
|
||||||
tutorialTimer = 0.0f;
|
tutorialTimer = 0.0f;
|
||||||
degrading2ActivationCountdown = -1;
|
degrading2ActivationCountdown = -1;
|
||||||
@@ -204,6 +209,9 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
|
|
||||||
crew = GameMain.GameSession.CrewManager.GetCharacters().ToList();
|
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
|
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
|
||||||
started = true;
|
started = true;
|
||||||
}
|
}
|
||||||
@@ -224,6 +232,24 @@ namespace Barotrauma.Tutorials
|
|||||||
characterTimeOnSonar = 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.ObjectiveArea, holderFrame.RectTransform), style: null);
|
||||||
|
|
||||||
|
int toggleButtonWidth = (int)(30 * GUI.Scale);
|
||||||
|
var toggleButton = new GUIButton(new RectTransform(new Point(toggleButtonWidth, HUDLayoutSettings.ObjectiveArea.Height), 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
base.AddToGUIUpdateList();
|
base.AddToGUIUpdateList();
|
||||||
@@ -254,7 +280,7 @@ namespace Barotrauma.Tutorials
|
|||||||
|
|
||||||
for (int i = 0; i < activeObjectives.Count; i++)
|
for (int i = 0; i < activeObjectives.Count; i++)
|
||||||
{
|
{
|
||||||
CheckActiveObjectives(activeObjectives[i]);
|
CheckActiveObjectives(activeObjectives[i], deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,18 +288,41 @@ namespace Barotrauma.Tutorials
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(activeSegment.Objective))
|
if (!string.IsNullOrEmpty(activeSegment.Objective))
|
||||||
{
|
{
|
||||||
if (objectiveFrame == null)
|
AddNewObjective(activeSegment);
|
||||||
{
|
|
||||||
CreateObjectiveFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
objectiveText.Text = activeSegment.Objective;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activeSegment = null;
|
activeSegment = null;
|
||||||
ContentRunning = false;
|
ContentRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddNewObjective(TutorialSegment segment)
|
||||||
|
{
|
||||||
|
activeObjectives.Add(segment);
|
||||||
|
|
||||||
|
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.0f + (2.5f * activeObjectives.Count - 1)), objectiveFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), TextManager.Get("Objective"), textColor: Color.White, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight);
|
||||||
|
segment.LinkedText = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f + (2.5f * activeObjectives.Count - 1)), objectiveFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), segment.Objective, textColor: new Color(4, 180, 108), font: GUI.ObjectiveNameFont, textAlignment: Alignment.CenterRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveCompletedObjective(TutorialSegment objective)
|
||||||
|
{
|
||||||
|
objective.LinkedTitle.FadeOut(1f, true);
|
||||||
|
objective.LinkedText.FadeOut(1f, true);
|
||||||
|
|
||||||
|
CoroutineManager.StartCoroutine(WaitForObjectiveFade(objective));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<object> WaitForObjectiveFade(TutorialSegment objective)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(1f);
|
||||||
|
activeObjectives.Remove(objective);
|
||||||
|
|
||||||
|
for (int i = 0; i < activeObjectives.Count; i++)
|
||||||
|
{
|
||||||
|
activeObjectives[i].LinkedTitle.RectTransform.RelativeSize = new Vector2(0.8f, 0.0f + (2.5f * activeObjectives.Count - 1f));
|
||||||
|
activeObjectives[i].LinkedText.RectTransform.RelativeSize = new Vector2(0.8f, 1f + (2.5f * activeObjectives.Count - 1f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool CheckContextualTutorials(int index, float deltaTime)
|
private bool CheckContextualTutorials(int index, float deltaTime)
|
||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
@@ -285,24 +334,24 @@ namespace Barotrauma.Tutorials
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // Command Reactor: 10 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
|
case 1: // Command Reactor: 2 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
|
||||||
if (tutorialTimer < 10.5f)
|
if (tutorialTimer < 2.5f)
|
||||||
{
|
{
|
||||||
tutorialTimer += deltaTime;
|
tutorialTimer += deltaTime;
|
||||||
|
|
||||||
if (HasOrder("operatereactor"))
|
if (HasOrder("operatereactor"))
|
||||||
{
|
{
|
||||||
segments[index].IsTriggered = true;
|
segments[index].IsTriggered = true;
|
||||||
tutorialTimer = 10.5f;
|
tutorialTimer = 2.5f;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // Nav Console: 20 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
|
case 2: // Nav Console: 2 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
|
||||||
|
if (!segments[1].IsTriggered || !IsReactorPoweredUp()) return false; // Do not advance tutorial based on this segment if reactor has not been powered up
|
||||||
if (Character.Controlled?.SelectedConstruction != navConsole.Item)
|
if (Character.Controlled?.SelectedConstruction != navConsole.Item)
|
||||||
{
|
{
|
||||||
if (!segments[1].IsTriggered) return false; // Do not advance tutorial timer based on this segment if reactor has not been powered up
|
if (tutorialTimer < 4.5f)
|
||||||
if (tutorialTimer < 30.5f)
|
|
||||||
{
|
{
|
||||||
tutorialTimer += deltaTime;
|
tutorialTimer += deltaTime;
|
||||||
return false;
|
return false;
|
||||||
@@ -310,16 +359,7 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!segments[1].IsTriggered || !HasOrder("operatereactor")) // If reactor has not been powered up or ordered to be, default to that one first
|
tutorialTimer = 4.5f;
|
||||||
{
|
|
||||||
if (tutorialTimer < 10.5f)
|
|
||||||
{
|
|
||||||
tutorialTimer = 10.5f;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tutorialTimer = 30.5f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||||
@@ -377,6 +417,10 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8: // Degrading2: 5 seconds after 'Degrading1' dismissed, and only if player has not assigned any crew to perform maintenance [Video]
|
case 8: // Degrading2: 5 seconds after 'Degrading1' dismissed, and only if player has not assigned any crew to perform maintenance [Video]
|
||||||
|
if ((mechanic == null || mechanic.IsDead) && (engineer == null || engineer.IsDead)) // Both engineer and mechanic are dead or do not exist -> do not display
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (degrading2ActivationCountdown == -1f)
|
if (degrading2ActivationCountdown == -1f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -384,7 +428,7 @@ namespace Barotrauma.Tutorials
|
|||||||
else if (degrading2ActivationCountdown > 0.0f)
|
else if (degrading2ActivationCountdown > 0.0f)
|
||||||
{
|
{
|
||||||
degrading2ActivationCountdown -= deltaTime;
|
degrading2ActivationCountdown -= deltaTime;
|
||||||
if (HasOrder("repairsystems"))
|
if (HasOrder("repairsystems", "jobspecific"))
|
||||||
{
|
{
|
||||||
segments[index].IsTriggered = true;
|
segments[index].IsTriggered = true;
|
||||||
}
|
}
|
||||||
@@ -393,20 +437,19 @@ namespace Barotrauma.Tutorials
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9: // Medical: Crewmember is injured but not killed [Video]
|
case 9: // Medical: Crewmember is injured but not killed [Video]
|
||||||
bool injuredFound = false;
|
|
||||||
for (int i = 0; i < crew.Count; i++)
|
for (int i = 0; i < crew.Count; i++)
|
||||||
{
|
{
|
||||||
Character member = crew[i];
|
Character member = crew[i];
|
||||||
if (member.Vitality < member.MaxVitality && !member.IsDead)
|
if (member.Vitality < member.MaxVitality && !member.IsDead)
|
||||||
{
|
{
|
||||||
injuredFound = true;
|
injuredMember = member;
|
||||||
TriggerTutorialSegment(index, new string[] { member.DisplayName,
|
TriggerTutorialSegment(index, new string[] { member.Info.DisplayName,
|
||||||
(member.Info.Gender == Gender.Male) ? TextManager.Get("PronounPossessiveMale").ToLower() : TextManager.Get("PronounPossessiveFemale").ToLower() });
|
(member.Info.Gender == Gender.Male) ? TextManager.Get("PronounPossessiveMale").ToLower() : TextManager.Get("PronounPossessiveFemale").ToLower() });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!injuredFound) return false;
|
if (injuredMember == null) return false;
|
||||||
break;
|
break;
|
||||||
case 10: // Approach1: Destination is within ~100m [Video]
|
case 10: // Approach1: Destination is within ~100m [Video]
|
||||||
if (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 8000f)
|
if (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 8000f)
|
||||||
@@ -430,34 +473,125 @@ namespace Barotrauma.Tutorials
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckActiveObjectives(TutorialSegment objective)
|
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)
|
switch(objective.Id)
|
||||||
{
|
{
|
||||||
case "ReactorCommand": // Reactor up and running
|
case "ReactorCommand": // Reactor up and running
|
||||||
|
if (!IsReactorPoweredUp()) return;
|
||||||
break;
|
break;
|
||||||
case "NavConsole": // traveled 100 meters
|
case "NavConsole": // traveled 50 meters
|
||||||
|
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 4000f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Flood": // Hull breaches repaired
|
case "Flood": // Hull breaches repaired
|
||||||
|
if (IsFlooding()) return;
|
||||||
break;
|
break;
|
||||||
case "EnemyOnSonar":
|
case "Medical":
|
||||||
|
if (injuredMember.Vitality < injuredMember.MaxVitality && !injuredMember.IsDead)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Degrading2":
|
case "EnemyOnSonar": // Enemy dispatched
|
||||||
|
if (HasEnemyOnSonarForDuration(deltaTime))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Approach1":
|
case "Degrading2": // 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
activeObjectives.Remove(objective);
|
RemoveCompletedObjective(objective);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HasOrder(string aiTag)
|
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)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < crew.Count; i++)
|
for (int i = 0; i < crew.Count; i++)
|
||||||
{
|
{
|
||||||
if (crew[i].CurrentOrder?.AITag == aiTag) return true;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -531,7 +665,7 @@ namespace Barotrauma.Tutorials
|
|||||||
objectiveText = string.Format(activeSegment.Objective, args);
|
objectiveText = string.Format(activeSegment.Objective, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
activeObjectives.Add(activeSegment);
|
activeSegment.Objective = objectiveText;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (activeSegment.ContentType)
|
switch (activeSegment.ContentType)
|
||||||
@@ -558,26 +692,6 @@ namespace Barotrauma.Tutorials
|
|||||||
CoroutineManager.StartCoroutine(WaitToStop()); // Completed
|
CoroutineManager.StartCoroutine(WaitToStop()); // Completed
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateObjectiveFrame()
|
|
||||||
{
|
|
||||||
holderFrame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center));
|
|
||||||
objectiveFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ObjectiveArea, holderFrame.RectTransform), style: null);
|
|
||||||
objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.3f), objectiveFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), TextManager.Get("Objective"), textColor: Color.White, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.BottomRight);
|
|
||||||
objectiveText = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.7f), objectiveFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter), "Repair Hull Breach", textColor: new Color(4, 180, 108), font: GUI.ObjectiveNameFont, textAlignment: Alignment.TopRight);
|
|
||||||
|
|
||||||
int toggleButtonWidth = (int)(30 * GUI.Scale);
|
|
||||||
var toggleButton = new GUIButton(new RectTransform(new Point(toggleButtonWidth, HUDLayoutSettings.ObjectiveArea.Height), objectiveFrame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(0, -5) }, 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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<object> WaitToStop()
|
private IEnumerable<object> WaitToStop()
|
||||||
{
|
{
|
||||||
while (ContentRunning) yield return null;
|
while (ContentRunning) yield return null;
|
||||||
|
|||||||
@@ -1386,6 +1386,9 @@ namespace Barotrauma.Networking
|
|||||||
case ServerNetObject.CLIENT_LIST:
|
case ServerNetObject.CLIENT_LIST:
|
||||||
ReadClientList(inc);
|
ReadClientList(inc);
|
||||||
break;
|
break;
|
||||||
|
case ServerNetObject.CLIENT_LIST:
|
||||||
|
ReadClientList(inc);
|
||||||
|
break;
|
||||||
case ServerNetObject.CHAT_MESSAGE:
|
case ServerNetObject.CHAT_MESSAGE:
|
||||||
ChatMessage.ClientRead(inc);
|
ChatMessage.ClientRead(inc);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1018,6 +1018,10 @@ namespace Barotrauma
|
|||||||
targetingTag = targetCharacter.SpeciesName.ToLowerInvariant();
|
targetingTag = targetCharacter.SpeciesName.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
else if (targetingPriorities.ContainsKey(targetCharacter.SpeciesName.ToLowerInvariant()))
|
else if (targetingPriorities.ContainsKey(targetCharacter.SpeciesName.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
targetingTag = targetCharacter.SpeciesName.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
else if (targetingPriorities.ContainsKey(targetCharacter.SpeciesName.ToLowerInvariant()))
|
||||||
{
|
{
|
||||||
if (targetCharacter.AIController is EnemyAIController enemy)
|
if (targetCharacter.AIController is EnemyAIController enemy)
|
||||||
{
|
{
|
||||||
@@ -1179,11 +1183,6 @@ namespace Barotrauma
|
|||||||
Character.AnimController.ReleaseStuckLimbs();
|
Character.AnimController.ReleaseStuckLimbs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetMinimumPassableHoleCount()
|
|
||||||
{
|
|
||||||
return (int)Math.Ceiling(ConvertUnits.ToDisplayUnits(colliderSize) / Structure.WallSectionSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected override void OnStateChanged(AIState from, AIState to)
|
protected override void OnStateChanged(AIState from, AIState to)
|
||||||
|
|||||||
@@ -1049,6 +1049,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
CheckValidity();
|
CheckValidity();
|
||||||
|
|
||||||
|
CheckValidity();
|
||||||
|
|
||||||
UpdateNetPlayerPosition(deltaTime);
|
UpdateNetPlayerPosition(deltaTime);
|
||||||
CheckDistFromCollider();
|
CheckDistFromCollider();
|
||||||
UpdateCollisionCategories();
|
UpdateCollisionCategories();
|
||||||
|
|||||||
@@ -204,6 +204,9 @@ namespace Barotrauma
|
|||||||
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
|
Hull hull = Hull.FindHull(ConvertUnits.ToDisplayUnits(explosionPos), null, false);
|
||||||
bool underWater = hull == null || explosionPos.Y < hull.Surface;
|
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);
|
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
|
||||||
|
|
||||||
Dictionary<Limb, float> distFactors = new Dictionary<Limb, float>();
|
Dictionary<Limb, float> distFactors = new Dictionary<Limb, float>();
|
||||||
|
|||||||
@@ -120,6 +120,18 @@ namespace Barotrauma
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 LinearVelocity
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float AngularVelocity
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly float Timestamp;
|
public readonly float Timestamp;
|
||||||
public readonly UInt16 ID;
|
public readonly UInt16 ID;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user