(e42047dc1) Tester's build, January 30th 2020

This commit is contained in:
Juan Pablo Arce
2020-01-30 15:56:31 -03:00
parent eaa18a20a3
commit 15499cb704
203 changed files with 8274 additions and 4950 deletions
+1
View File
@@ -0,0 +1 @@
Content/*
@@ -9,10 +9,14 @@ namespace Barotrauma
{
public static List<AITarget> List = new List<AITarget>();
private Entity entity;
public Entity Entity
{
get;
private set;
get
{
if (entity != null && entity.Removed) { return null; }
return entity;
}
}
private float soundRange;
@@ -28,13 +32,29 @@ namespace Barotrauma
public float SoundRange
{
get { return soundRange; }
set { soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange); }
set
{
if (float.IsNaN(value))
{
DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace);
return;
}
soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
}
}
public float SightRange
{
get { return sightRange; }
set { sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange); }
set
{
if (float.IsNaN(value))
{
DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace);
return;
}
sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
}
}
private float sectorRad = MathHelper.TwoPi;
@@ -54,7 +74,7 @@ namespace Barotrauma
{
string errorMsg = "Invalid AITarget sector direction (" + value + ")\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + Entity?.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + entity?.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
sectorDir = value;
@@ -88,7 +108,7 @@ namespace Barotrauma
{
get
{
if (Entity == null || Entity.Removed)
if (entity == null || entity.Removed)
{
#if DEBUG
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
@@ -99,7 +119,7 @@ namespace Barotrauma
return Vector2.Zero;
}
return Entity.WorldPosition;
return entity.WorldPosition;
}
}
@@ -107,7 +127,7 @@ namespace Barotrauma
{
get
{
if (Entity == null || Entity.Removed)
if (entity == null || entity.Removed)
{
#if DEBUG
DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace);
@@ -118,7 +138,7 @@ namespace Barotrauma
return Vector2.Zero;
}
return Entity.SimPosition;
return entity.SimPosition;
}
}
@@ -156,7 +176,7 @@ namespace Barotrauma
public AITarget(Entity e)
{
Entity = e;
entity = e;
List.Add(this);
}
@@ -181,7 +201,7 @@ namespace Barotrauma
public void Remove()
{
List.Remove(this);
Entity = null;
entity = null;
}
}
}
@@ -89,6 +89,9 @@ namespace Barotrauma
private readonly float memoryFadeTime = 0.5f;
private readonly float avoidTime = 3;
//Has the character been attacked since the last Update.
private bool wasAttacked;
private float avoidTimer;
public LatchOntoAI LatchOntoAI { get; private set; }
@@ -231,7 +234,15 @@ namespace Barotrauma
public override void Update(float deltaTime)
{
if (wasAttacked)
{
LatchOntoAI?.DeattachFromBody();
Character.AnimController.ReleaseStuckLimbs();
wasAttacked = false;
}
if (DisableEnemyAI) { return; }
base.Update(deltaTime);
bool ignorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X));
@@ -630,7 +641,7 @@ namespace Barotrauma
if (pickable != null)
{
var target = pickable.Picker?.AiTarget;
if (target != null)
if (target?.Entity != null && !target.Entity.Removed)
{
SelectedAiTarget = target;
}
@@ -1224,14 +1235,13 @@ namespace Barotrauma
}
return isDisabled;
}
public override void OnAttacked(Character attacker, AttackResult attackResult)
{
float reactionTime = Rand.Range(0.1f, 0.3f);
updateTargetsTimer = Math.Min(updateTargetsTimer, reactionTime);
LatchOntoAI?.DeattachFromBody();
Character.AnimController.ReleaseStuckLimbs();
wasAttacked = true;
if (attacker == null || attacker.AiTarget == null) { return; }
@@ -131,6 +131,8 @@ namespace Barotrauma
}
coroutine = CoroutineManager.InvokeAfter(() =>
{
//round ended before the coroutine finished
if (GameMain.GameSession == null || Level.Loaded == null) { return; }
DelayedObjectives.Remove(objective);
AddObjective(objective);
callback?.Invoke();
@@ -2,15 +2,30 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using System.Linq;
namespace Barotrauma
{
public enum OrderCategory
{
Emergency,
Movement,
Power,
Maintenance,
Operate,
Undefined
}
class Order
{
public static Dictionary<string, Order> Prefabs { get; private set; }
public static Dictionary<OrderCategory, Sprite> OrderCategoryIcons { get; private set; }
public static Sprite StartNode { get; private set; }
public static Sprite ShortcutNode { get; private set; }
public static Sprite ExpandNode { get; private set; }
public static Sprite NodeContainer { get; private set; }
public static Sprite CommandBackground { get; private set; }
public static List<Order> PrefabList { get; private set; }
public static Order GetPrefab(string identifier)
{
@@ -49,15 +64,20 @@ namespace Barotrauma
public Controller ConnectedController;
public Character OrderGiver;
public readonly OrderCategory Category;
//legacy support
public readonly string[] AppropriateJobs;
public readonly string[] Options;
public readonly string[] OptionNames;
public readonly Dictionary<string, Sprite> OptionSprites;
static Order()
{
Prefabs = new Dictionary<string, Order>();
OrderCategoryIcons = new Dictionary<OrderCategory, Sprite>();
foreach (ContentFile file in GameMain.Instance.GetFilesOfType(ContentType.Orders))
{
@@ -72,11 +92,11 @@ namespace Barotrauma
}
foreach (XElement sourceElement in mainElement.Elements())
{
var orderElement = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement;
string name = orderElement.Name.ToString();
var element = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement;
string name = element.Name.ToString();
if (name.Equals("order", StringComparison.OrdinalIgnoreCase))
{
string identifier = orderElement.GetAttributeString("identifier", null);
string identifier = element.GetAttributeString("identifier", null);
if (string.IsNullOrWhiteSpace(identifier))
{
DebugConsole.ThrowError($"Error in file {file.Path}: The order element '{name}' does not have an identifier! All orders must have a unique identifier.");
@@ -95,10 +115,58 @@ namespace Barotrauma
continue;
}
}
var newOrder = new Order(orderElement);
var newOrder = new Order(element);
newOrder.Prefab = newOrder;
Prefabs.Add(identifier, newOrder);
}
else if (name.Equals("ordercategory", StringComparison.OrdinalIgnoreCase))
{
var category = (OrderCategory)Enum.Parse(typeof(OrderCategory), element.GetAttributeString("category", "undefined"), true);
if (OrderCategoryIcons.TryGetValue(category, out Sprite duplicate))
{
if (allowOverriding || sourceElement.IsOverride())
{
DebugConsole.NewMessage($"Overriding an existing icon for the '{category}' order category with another one defined in '{file}'", Color.Yellow);
OrderCategoryIcons.Remove(category);
}
else
{
DebugConsole.ThrowError($"Error in file {file}: Duplicate element for the '{category}' order category found in '{file}'! All order categories must be unique. Use <override></override> tags to override an order category.");
continue;
}
}
var spriteElement = element.GetChildElement("sprite");
if (spriteElement != null)
{
var sprite = new Sprite(spriteElement, lazyLoad: true);
OrderCategoryIcons.Add(category, sprite);
}
}
else
{
var spriteElement = element.GetChildElement("sprite");
if (spriteElement != null)
{
switch (name.ToLowerInvariant())
{
case "startnode":
StartNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "shortcutnode":
ShortcutNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "expandnode":
ExpandNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "nodecontainer":
NodeContainer = new Sprite(spriteElement, lazyLoad: true);
break;
case "commandbackground":
CommandBackground = new Sprite(spriteElement, lazyLoad: true);
break;
}
}
}
}
}
PrefabList = new List<Order>(Prefabs.Values);
@@ -130,6 +198,7 @@ namespace Barotrauma
TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false);
AppropriateJobs = orderElement.GetAttributeStringArray("appropriatejobs", new string[0]);
Options = orderElement.GetAttributeStringArray("options", new string[0]);
Category = (OrderCategory)Enum.Parse(typeof(OrderCategory), orderElement.GetAttributeString("category", "undefined"), true);
string translatedOptionNames = TextManager.Get("OrderOptions." + Identifier, true);
if (translatedOptionNames == null)
@@ -152,13 +221,24 @@ namespace Barotrauma
OptionNames = Options;
}
foreach (XElement subElement in orderElement.Elements())
var spriteElement = orderElement.GetChildElement("sprite");
if (spriteElement != null)
{
switch (subElement.Name.ToString().ToLowerInvariant())
SymbolSprite = new Sprite(spriteElement, lazyLoad: true);
}
OptionSprites = new Dictionary<string, Sprite>();
if (Options != null && Options.Length > 0)
{
var optionSpriteElements = orderElement.GetChildElement("optionsprites")?.GetChildElements("sprite");
if (optionSpriteElements != null && optionSpriteElements.Any())
{
case "sprite":
SymbolSprite = new Sprite(subElement, lazyLoad: true);
break;
for (int i = 0; i < Options.Length; i++)
{
if (i >= optionSpriteElements.Count()) { break; };
var sprite = new Sprite(optionSpriteElements.ElementAt(i), lazyLoad: true);
OptionSprites.Add(Options[i], sprite);
}
}
}
}
@@ -226,5 +306,4 @@ namespace Barotrauma
return msg;
}
}
}
@@ -1789,7 +1789,7 @@ namespace Barotrauma
}
}
item.SetTransform(currItemPos, itemAngle + itemAngleRelativeToHoldAngle * Dir);
item.SetTransform(currItemPos, itemAngle + itemAngleRelativeToHoldAngle * Dir, setPrevTransform: false);
if (!isClimbing)
{
@@ -958,8 +958,8 @@ namespace Barotrauma
else
{
if (character.Position.X < gap.Rect.X || character.Position.X > gap.Rect.Right) continue;
if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2)) !=
Math.Sign(character.Position.X - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2)))
if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2)) !=
Math.Sign(character.Position.Y - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2)))
{
continue;
}
@@ -311,6 +311,21 @@ namespace Barotrauma
selectedCharacter = value;
if (selectedCharacter != null)
selectedCharacter.selectedBy = this;
#if CLIENT
if (GameMain.GameSession == null) return;
// Quick & dirty hiding of the chat whenever a character with an accessible inventory is selected to prevent overlaps
if (GameMain.GameSession.CrewManager.IsSinglePlayer)
{
if (GameMain.GameSession.CrewManager.ChatBox == null) return;
GameMain.GameSession.CrewManager.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed));
}
else
{
if (GameMain.Client?.ChatBox == null) return;
GameMain.Client.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed));
}
#endif
}
}
@@ -260,6 +260,11 @@ namespace Barotrauma
}
}
#if CLIENT
private Sprite jobIcon;
private Vector2 jobIconPos;
#endif
private Sprite portraitBackground;
public Sprite PortraitBackground
{
@@ -442,6 +447,13 @@ namespace Barotrauma
CalculateHeadSpriteRange();
Head.HeadSpriteId = GetRandomHeadID();
Job = (jobPrefab == null) ? Job.Random(Rand.RandSync.Server) : new Job(jobPrefab, variant);
#if CLIENT
jobIcon = Job.Prefab.Icon;
//TODO: fix jobIconPos
jobIconPos = new Vector2(HUDLayoutSettings.HealthBarAreaLeft.Right, HUDLayoutSettings.HealthBarAreaLeft.Y - HUDLayoutSettings.Padding);
GameMain.Instance.OnResolutionChanged += () => jobIconPos = new Vector2(HUDLayoutSettings.HealthBarAreaLeft.Right, HUDLayoutSettings.HealthBarAreaLeft.Y - HUDLayoutSettings.Padding);
#endif
if (!string.IsNullOrEmpty(name))
{
Name = name;
@@ -145,7 +145,7 @@ namespace Barotrauma
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
if (currentEffect == null) return 0.0f;
if (currentEffect.MaxResistance - currentEffect.MinResistance <= 0.0f) return 0.0f;
if (afflictionId != currentEffect.ResistanceFor) return 0.0f;
if (afflictionId != null && afflictionId != currentEffect.ResistanceFor) return 0.0f;
return MathHelper.Lerp(
currentEffect.MinResistance,
@@ -256,7 +256,7 @@ namespace Barotrauma
public readonly string AchievementOnRemoved;
public readonly Sprite Icon;
public readonly Color IconColor;
public readonly Color[] IconColors;
private List<Effect> effects = new List<Effect>();
@@ -510,7 +510,7 @@ namespace Barotrauma
CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + Identifier, true) ?? element.GetAttributeString("causeofdeathdescription", "");
SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + Identifier, true) ?? element.GetAttributeString("selfcauseofdeathdescription", "");
IconColors = element.GetAttributeColorArray("iconcolors", null);
AchievementOnRemoved = element.GetAttributeString("achievementonremoved", "");
foreach (XElement subElement in element.Elements())
@@ -519,7 +519,6 @@ namespace Barotrauma
{
case "icon":
Icon = new Sprite(subElement);
IconColor = subElement.GetAttributeColor("color", Color.White);
break;
case "effect":
effects.Add(new Effect(subElement, Name));
@@ -160,6 +160,7 @@ namespace Barotrauma
private set;
}
public Sprite Icon;
public string FilePath { get; private set; }
public XElement Element { get; private set; }
@@ -200,6 +201,9 @@ namespace Barotrauma
case "appropriateorders":
subElement.Elements().ForEach(order => AppropriateOrders.Add(order.GetAttributeString("identifier", "").ToLowerInvariant()));
break;
case "icon":
Icon = new Sprite(subElement.FirstElement());
break;
}
}
@@ -244,76 +248,6 @@ namespace Barotrauma
ClothingElement = element.GetChildElement("PortraitClothing");
}
public class OutfitPreview
{
/// <summary>
/// Pair.First = sprite, Pair.Second = draw offset
/// </summary>
public readonly List<Pair<Sprite, Vector2>> Sprites;
public Vector2 Dimensions;
public OutfitPreview()
{
Sprites = new List<Pair<Sprite, Vector2>>();
Dimensions = Vector2.One;
}
public void AddSprite(Sprite sprite, Vector2 drawOffset)
{
Sprites.Add(new Pair<Sprite, Vector2>(sprite, drawOffset));
}
}
public List<OutfitPreview> GetJobOutfitSprites(Gender gender, out Vector2 maxDimensions)
{
List<OutfitPreview> outfitPreviews = new List<OutfitPreview>();
maxDimensions = Vector2.One;
var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeString("identifier", ""));
var outfitPrefabs = ItemPrefab.Prefabs.Where(itemPrefab => equipIdentifiers.Contains(itemPrefab.Identifier)).ToList();
if (!outfitPrefabs.Any()) { return null; }
for (int i = 0; i < outfitPrefabs.Count; i++)
{
var outfitPreview = new OutfitPreview();
if (!ItemSets.TryGetValue(i, out var itemSetElement)) { continue; }
var previewElement = itemSetElement.GetChildElement("PreviewSprites");
if (previewElement == null)
{
#if CLIENT
if (outfitPrefabs[i] is ItemPrefab prefab && prefab.InventoryIcon != null)
{
outfitPreview.AddSprite(prefab.InventoryIcon, Vector2.Zero);
outfitPreview.Dimensions = prefab.InventoryIcon.SourceRect.Size.ToVector2();
maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X);
maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y);
}
#endif
outfitPreviews.Add(outfitPreview);
continue;
}
var children = previewElement.Elements().ToList();
for (int n = 0; n < children.Count; n++)
{
XElement spriteElement = children[n];
string spriteTexture = spriteElement.GetAttributeString("texture", "").Replace("[GENDER]", (gender == Gender.Female) ? "female" : "male");
var sprite = new Sprite(spriteElement, file: spriteTexture);
sprite.size = new Vector2(sprite.SourceRect.Width, sprite.SourceRect.Height);
outfitPreview.AddSprite(sprite, children[n].GetAttributeVector2("offset", Vector2.Zero));
}
outfitPreview.Dimensions = previewElement.GetAttributeVector2("dims", Vector2.One);
maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X);
maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y);
outfitPreviews.Add(outfitPreview);
}
return outfitPreviews;
}
public static JobPrefab Random(Rand.RandSync sync = Rand.RandSync.Unsynced) => Prefabs.GetRandom(sync);
@@ -1210,7 +1210,7 @@ namespace Barotrauma
return;
}
if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") return;
if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") { return; }
string[] splitCommand = SplitCommand(command);
if (splitCommand.Length == 0)
@@ -1231,12 +1231,17 @@ namespace Barotrauma
#if CLIENT
if (GameMain.Client != null)
{
if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant()))
Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant()));
if (matchingCommand == null)
{
Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant()));
//if the command is not defined client-side, we'll relay it anyway because it may be a custom command at the server's side
if (matchingCommand == null || matchingCommand.RelayToServer)
GameMain.Client.SendConsoleCommand(command);
NewMessage("Server command: " + command, Color.White);
return;
}
else if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant()))
{
if (matchingCommand.RelayToServer)
{
GameMain.Client.SendConsoleCommand(command);
NewMessage("Server command: " + command, Color.White);
@@ -1245,7 +1250,6 @@ namespace Barotrauma
{
matchingCommand.ClientExecute(splitCommand.Skip(1).ToArray());
}
return;
}
}
@@ -258,6 +258,9 @@ namespace Barotrauma
{
CoroutineManager.InvokeAfter(() =>
{
//round ended before the coroutine finished
if (GameMain.GameSession == null || Level.Loaded == null) { return; }
System.Diagnostics.Debug.Assert(GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer, "Clients should not create monster events.");
monsters.Add(Character.Create(speciesName, spawnPos.Value + Rand.Vector(offsetAmount), Level.Loaded.Seed + i.ToString(), null, false, true, true));
@@ -37,11 +37,22 @@ namespace Barotrauma.Extensions
return new Point((int)(p.X / v.X), (int)(p.Y / v.Y));
}
/// <summary>
/// Negates the X and Y components.
/// </summary>
public static Point Inverse(this Point p)
{
return new Point(-p.X, -p.Y);
}
/// <summary>
/// Flips the X and Y components.
/// </summary>
public static Point Flip(this Point p)
{
return new Point(p.Y, p.X);
}
public static Point Clamp(this Point p, Point min, Point max)
{
return new Point(MathHelper.Clamp(p.X, min.X, max.X), MathHelper.Clamp(p.Y, min.Y, max.Y));
@@ -1,9 +1,6 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma
{
@@ -14,22 +11,12 @@ namespace Barotrauma
private float conversationTimer, conversationLineTimer;
private List<Pair<Character, string>> pendingConversationLines = new List<Pair<Character, string>>();
//orders that have not been issued to a specific character
private List<Pair<Order, float>> activeOrders = new List<Pair<Order, float>>();
public List<Pair<Order, float>> ActiveOrders
{
get { return activeOrders; }
}
private bool isSinglePlayer;
public bool IsSinglePlayer
{
get { return isSinglePlayer; }
}
public List<Pair<Order, float>> ActiveOrders { get; } = new List<Pair<Order, float>>();
public bool IsSinglePlayer { get; private set; }
public CrewManager(bool isSinglePlayer)
{
this.isSinglePlayer = isSinglePlayer;
IsSinglePlayer = isSinglePlayer;
conversationTimer = 5.0f;
InitProjectSpecific();
@@ -45,7 +32,7 @@ namespace Barotrauma
return false;
}
Pair<Order, float> existingOrder = activeOrders.Find(o => o.First.Prefab == order.Prefab && o.First.TargetEntity == order.TargetEntity);
Pair<Order, float> existingOrder = ActiveOrders.Find(o => o.First.Prefab == order.Prefab && o.First.TargetEntity == order.TargetEntity);
if (existingOrder != null)
{
existingOrder.Second = fadeOutTime;
@@ -53,23 +40,23 @@ namespace Barotrauma
}
else
{
activeOrders.Add(new Pair<Order, float>(order, fadeOutTime));
ActiveOrders.Add(new Pair<Order, float>(order, fadeOutTime));
return true;
}
}
public void RemoveOrder(Order order)
{
activeOrders.RemoveAll(o => o.First == order);
ActiveOrders.RemoveAll(o => o.First == order);
}
public void Update(float deltaTime)
{
foreach (Pair<Order, float> order in activeOrders)
foreach (Pair<Order, float> order in ActiveOrders)
{
order.Second -= deltaTime;
}
activeOrders.RemoveAll(o => o.Second <= 0.0f);
ActiveOrders.RemoveAll(o => o.Second <= 0.0f);
UpdateConversations(deltaTime);
UpdateProjectSpecific(deltaTime);
@@ -288,7 +288,7 @@ namespace Barotrauma
#if CLIENT
if (GameMode is SinglePlayerCampaign) { SteamAchievementManager.OnBiomeDiscovered(level.Biome); }
roundSummary = new RoundSummary(this);
RoundSummary = new RoundSummary(this);
GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
@@ -325,9 +325,9 @@ namespace Barotrauma
(Mission == null ? "None" : Mission.GetType().ToString()));
#if CLIENT
if (roundSummary != null)
if (RoundSummary != null)
{
GUIFrame summaryFrame = roundSummary.CreateSummaryFrame(endMessage);
GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(endMessage);
GUIMessageBox.MessageBoxes.Add(summaryFrame);
var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), summaryFrame.Children.First().Children.First().FindChild("buttonarea").RectTransform),
TextManager.Get("OK"))
@@ -234,6 +234,9 @@ namespace Barotrauma
public volatile bool SuppressModFolderWatcher;
#if DEBUG
public bool AutomaticQuickStartEnabled { get; set; }
#endif
private FileSystemWatcher modsFolderWatcher;
@@ -1196,7 +1199,11 @@ namespace Barotrauma
new XAttribute("crewmenuopen", CrewMenuOpen),
new XAttribute("campaigndisclaimershown", CampaignDisclaimerShown),
new XAttribute("editordisclaimershown", EditorDisclaimerShown),
new XAttribute("tutorialskipwarning", ShowTutorialSkipWarning));
new XAttribute("tutorialskipwarning", ShowTutorialSkipWarning)
#if DEBUG
, new XAttribute("automaticquickstartenabled", AutomaticQuickStartEnabled)
#endif
);
if (!string.IsNullOrEmpty(overrideSaveFolder))
{
@@ -1378,6 +1385,9 @@ namespace Barotrauma
CampaignDisclaimerShown = doc.Root.GetAttributeBool("campaigndisclaimershown", CampaignDisclaimerShown);
EditorDisclaimerShown = doc.Root.GetAttributeBool("editordisclaimershown", EditorDisclaimerShown);
ShowTutorialSkipWarning = doc.Root.GetAttributeBool("tutorialskipwarning", true);
#if DEBUG
AutomaticQuickStartEnabled = doc.Root.GetAttributeBool("automaticquickstartenabled", AutomaticQuickStartEnabled);
#endif
XElement gameplayElement = doc.Root.Element("gameplay");
jobPreferences = new List<Pair<string, int>>();
if (gameplayElement != null)
@@ -14,6 +14,8 @@ namespace Barotrauma
SelectPreviousCharacter,
Voice,
Deselect,
Shoot
Shoot,
Command,
ToggleInventory
}
}
@@ -199,7 +199,7 @@ namespace Barotrauma
#if CLIENT
for (int j = 0; j < capacity; j++)
{
if (slots != null && Items[j] == Items[i]) slots[j].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
if (slots != null && Items[j] == Items[i]) slots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
}
#endif
}
@@ -300,7 +300,7 @@ namespace Barotrauma.Items.Components
#if CLIENT
else if (hasRequiredItems && character != null && character == Character.Controlled)
{
GUI.AddMessage(accessDeniedTxt, Color.Red);
GUI.AddMessage(accessDeniedTxt, GUI.Style.Red);
}
#endif
@@ -139,7 +139,7 @@ namespace Barotrauma.Items.Components
this,
item.WorldPosition,
pickTimer / requiredTime,
Color.Red, Color.Green);
GUI.Style.Red, GUI.Style.Green);
#endif
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
@@ -462,7 +462,7 @@ namespace Barotrauma.Items.Components
this,
targetItem.WorldPosition,
levelResource.DeattachTimer / levelResource.DeattachDuration,
Color.Red, Color.Green);
GUI.Style.Red, GUI.Style.Green);
#endif
}
FixItemProjSpecific(user, deltaTime, targetItem);
@@ -504,11 +504,12 @@ namespace Barotrauma.Items.Components
loopingSoundChannel = null;
}
foreach (SoundChannel channel in playingOneshotSoundChannels)
//no need to Dispose these - SoundManager will do it when it when it needs a free channel and the sound has stopped playing
//disposing immediately on Remove will for example prevent explosives from playing a sound if the explosion removes the item
/*foreach (SoundChannel channel in playingOneshotSoundChannels)
{
channel.Dispose();
loopingSoundChannel = null;
}
}*/
if (GuiFrame != null) { GUI.RemoveFromUpdateList(GuiFrame, true); }
#endif
@@ -85,7 +85,7 @@ namespace Barotrauma.Items.Components
currPowerConsumption = Math.Abs(targetForce) / 100.0f * powerConsumption;
//pumps consume more power when in a bad condition
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition);
if (powerConsumption == 0.0f) { Voltage = 1.0f; }
@@ -95,7 +95,8 @@ namespace Barotrauma.Items.Components
Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, 0.1f);
if (Math.Abs(Force) > 1.0f)
{
Vector2 currForce = new Vector2((force / 10.0f) * maxForce * Math.Min(Voltage / MinVoltage, 1.0f), 0.0f);
float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage / MinVoltage, 1.0f);
Vector2 currForce = new Vector2((force / 10.0f) * maxForce * voltageFactor, 0.0f);
//less effective when in a bad condition
currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.MaxCondition);
@@ -154,7 +154,7 @@ namespace Barotrauma.Items.Components
outputContainer.Inventory.Locked = true;
currPowerConsumption = powerConsumption;
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition);
}
private void CancelFabricating(Character user = null)
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
}
currPowerConsumption = powerConsumption;
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition);
hasPower = Voltage > MinVoltage;
if (hasPower)
@@ -42,7 +42,7 @@ namespace Barotrauma.Items.Components
CurrFlow = 0.0f;
currPowerConsumption = powerConsumption;
//consume more power when in a bad condition
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition);
if (powerConsumption <= 0.0f)
{
@@ -14,8 +14,6 @@ namespace Barotrauma.Items.Components
private float? targetLevel;
private float pumpSpeedLockTimer, isActiveLockTimer;
private bool hasPower;
[Serialize(0.0f, true, description: "How fast the item is currently pumping water (-100 = full speed out, 100 = full speed in). Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")]
public float FlowPercentage
@@ -23,7 +21,7 @@ namespace Barotrauma.Items.Components
get { return flowPercentage; }
set
{
if (!MathUtils.IsValid(flowPercentage)) return;
if (!MathUtils.IsValid(flowPercentage)) { return; }
flowPercentage = MathHelper.Clamp(value, -100.0f, 100.0f);
flowPercentage = MathUtils.Round(flowPercentage, 1.0f);
}
@@ -41,11 +39,26 @@ namespace Barotrauma.Items.Components
{
get
{
if (!IsActive) return 0.0f;
if (!IsActive) { return 0.0f; }
return Math.Abs(currFlow);
}
}
public override bool IsActive
{
get => base.IsActive;
set
{
base.IsActive = value;
if (!IsActive)
{
powerConsumption = 0;
}
}
}
public bool HasPower => IsActive && Voltage >= MinVoltage;
public Pump(Item item, XElement element)
: base(item, element)
{
@@ -57,7 +70,6 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
currFlow = 0.0f;
hasPower = false;
if (targetLevel != null)
{
@@ -74,14 +86,12 @@ namespace Barotrauma.Items.Components
currPowerConsumption = powerConsumption * Math.Abs(flowPercentage / 100.0f);
//pumps consume more power when in a bad condition
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition);
if (Voltage < MinVoltage) { return; }
if (!HasPower) { return; }
UpdateProjSpecific(deltaTime);
hasPower = true;
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
if (item.CurrentHull == null) { return; }
@@ -102,8 +112,8 @@ namespace Barotrauma.Items.Components
{
if (connection.Name == "toggle")
{
isActiveLockTimer = 0.1f;
IsActive = !IsActive;
isActiveLockTimer = 0.1f;
}
else if (connection.Name == "set_active")
{
@@ -126,21 +136,23 @@ namespace Barotrauma.Items.Components
pumpSpeedLockTimer = 0.1f;
}
}
if (!IsActive) currPowerConsumption = 0.0f;
}
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
#if CLIENT
if (GameMain.Client != null) return false;
if (GameMain.Client != null) { return false; }
#endif
if (objective.Option.ToLowerInvariant() == "stoppumping")
{
#if SERVER
if (FlowPercentage > 0.0f) item.CreateServerEvent(this);
if (FlowPercentage > 0.0f)
{
item.CreateServerEvent(this);
}
#endif
IsActive = false;
FlowPercentage = 0.0f;
}
else
@@ -48,7 +48,19 @@ namespace Barotrauma.Items.Components
private Vector2 optimalFissionRate, allowedFissionRate;
private Vector2 optimalTurbineOutput, allowedTurbineOutput;
private bool shutDown;
private bool _powerOn;
public bool PowerOn
{
get { return _powerOn; }
set
{
_powerOn = value;
#if CLIENT
UpdateUIElementStates();
#endif
}
}
private Character lastAIUser;
@@ -152,12 +164,7 @@ namespace Barotrauma.Items.Components
{
autoTemp = value;
#if CLIENT
if (autoTempSlider != null)
{
autoTempSlider.BarScroll = value ?
Math.Min(0.45f, autoTempSlider.BarScroll) :
Math.Max(0.55f, autoTempSlider.BarScroll);
}
UpdateUIElementStates();
#endif
}
}
@@ -257,7 +264,7 @@ namespace Barotrauma.Items.Components
}
currPowerConsumption += autoAdjustAmount;
if (shutDown)
if (!PowerOn)
{
targetFissionRate = 0.0f;
targetTurbineOutput = 0.0f;
@@ -472,8 +479,8 @@ namespace Barotrauma.Items.Components
targetFissionRate = Math.Max(targetFissionRate - deltaTime * 10.0f, 0.0f);
targetTurbineOutput = Math.Max(targetTurbineOutput - deltaTime * 10.0f, 0.0f);
#if CLIENT
fissionRateScrollBar.BarScroll = 1.0f - FissionRate / 100.0f;
turbineOutputScrollBar.BarScroll = 1.0f - TurbineOutput / 100.0f;
FissionRateScrollBar.BarScroll = 1.0f - FissionRate / 100.0f;
TurbineOutputScrollBar.BarScroll = 1.0f - TurbineOutput / 100.0f;
UpdateGraph(deltaTime);
#endif
}
@@ -582,14 +589,14 @@ namespace Barotrauma.Items.Components
LastUser = lastAIUser = character;
bool prevAutoTemp = autoTemp;
bool prevShutDown = shutDown;
bool prevPowerOn = _powerOn;
float prevFissionRate = targetFissionRate;
float prevTurbineOutput = targetTurbineOutput;
switch (objective.Option.ToLowerInvariant())
{
case "powerup":
shutDown = false;
PowerOn = true;
if (objective.Override || !autoTemp)
{
//characters with insufficient skill levels simply set the autotemp on instead of trying to adjust the temperature manually
@@ -604,24 +611,20 @@ namespace Barotrauma.Items.Components
}
}
#if CLIENT
onOffSwitch.BarScroll = 0.0f;
fissionRateScrollBar.BarScroll = FissionRate / 100.0f;
turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
FissionRateScrollBar.BarScroll = FissionRate / 100.0f;
TurbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f;
#endif
break;
case "shutdown":
#if CLIENT
onOffSwitch.BarScroll = 1.0f;
#endif
PowerOn = false;
AutoTemp = false;
shutDown = true;
targetFissionRate = 0.0f;
targetTurbineOutput = 0.0f;
break;
}
if (autoTemp != prevAutoTemp ||
prevShutDown != shutDown ||
prevPowerOn != _powerOn ||
Math.Abs(prevFissionRate - targetFissionRate) > 1.0f ||
Math.Abs(prevTurbineOutput - targetTurbineOutput) > 1.0f)
{
@@ -640,14 +643,11 @@ namespace Barotrauma.Items.Components
case "shutdown":
if (targetFissionRate > 0.0f || targetTurbineOutput > 0.0f)
{
shutDown = true;
PowerOn = false;
AutoTemp = false;
targetFissionRate = 0.0f;
targetTurbineOutput = 0.0f;
unsentChanges = true;
#if CLIENT
onOffSwitch.BarScroll = 1.0f;
#endif
}
break;
}
@@ -116,8 +116,7 @@ namespace Barotrauma.Items.Components
}
}
#if CLIENT
if (activeTickBox != null) activeTickBox.Selected = value == Mode.Active;
if (passiveTickBox != null) passiveTickBox.Selected = value == Mode.Passive;
UpdateGUIElements();
#endif
}
}
@@ -126,10 +125,9 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
connectedTransducers = new List<ConnectedTransducer>();
CurrentMode = Mode.Passive;
IsActive = true;
InitProjSpecific(element);
CurrentMode = Mode.Passive;
}
partial void InitProjSpecific(XElement element);
@@ -344,14 +342,10 @@ namespace Barotrauma.Items.Components
}
}
if (!item.CanClientAccess(c)) return;
if (!item.CanClientAccess(c)) { return; }
CurrentMode = isActive ? Mode.Active : Mode.Passive;
//TODO: cleanup
#if CLIENT
activeTickBox.Selected = currentMode == Mode.Active;
#endif
if (isActive)
{
zoom = MathHelper.Lerp(MinZoom, MaxZoom, zoomT);
@@ -363,8 +357,7 @@ namespace Barotrauma.Items.Components
}
#if CLIENT
zoomSlider.BarScroll = zoomT;
directionalTickBox.Selected = useDirectionalPing;
directionalSlider.BarScroll = pingDirectionT;
directionalModeSwitch.Selected = useDirectionalPing;
#endif
}
#if SERVER
@@ -58,19 +58,24 @@ namespace Barotrauma.Items.Components
get { return autoPilot; }
set
{
if (value == autoPilot) return;
if (value == autoPilot) { return; }
autoPilot = value;
#if CLIENT
autopilotTickBox.Selected = autoPilot;
manualTickBox.Selected = !autoPilot;
maintainPosTickBox.Enabled = autoPilot;
levelEndTickBox.Enabled = autoPilot;
levelStartTickBox.Enabled = autoPilot;
UpdateGUIElements();
#endif
if (autoPilot)
{
if (pathFinder == null) pathFinder = new PathFinder(WayPoint.WayPointList, false);
if (pathFinder == null)
{
pathFinder = new PathFinder(WayPoint.WayPointList, false);
}
MaintainPos = true;
if (posToMaintain == null)
{
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
}
}
else
{
@@ -272,7 +277,7 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
if (autoPilot)
if (AutoPilot)
{
UpdateAutoPilot(deltaTime);
float userSkill = 0.0f;
@@ -317,7 +322,7 @@ namespace Barotrauma.Items.Components
private void UpdateAutoPilot(float deltaTime)
{
if (controlledSub == null) return;
if (controlledSub == null) { return; }
if (posToMaintain != null)
{
Vector2 steeringVel = GetSteeringVelocity((Vector2)posToMaintain, 10.0f);
@@ -577,6 +577,8 @@ namespace Barotrauma.Items.Components
railSprite?.Remove(); railSprite = null;
#if CLIENT
crosshairSprite?.Remove(); crosshairSprite = null;
crosshairPointerSprite?.Remove(); crosshairPointerSprite = null;
moveSoundChannel?.Dispose(); moveSoundChannel = null;
#endif
}
@@ -37,13 +37,17 @@ namespace Barotrauma
#if CLIENT
this.slotsPerRow = slotsPerRow;
if (slotSpriteSmall == null)
if (SlotSpriteSmall == null)
{
//TODO: define these in xml
slotSpriteSmall = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(532, 395, 75, 71), null, 0);
SlotSpriteSmall = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(0, 0, 128, 128), null, 0);
// Adjustment to match the old size of 75,71
SlotSpriteSmall.size = new Vector2(SlotSpriteSmall.SourceRect.Width * 0.5859375f, SlotSpriteSmall.SourceRect.Height * 0.5546875f);
slotSpriteVertical = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(672, 218, 75, 144), null, 0);
slotSpriteHorizontal = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(476, 186, 160, 75), null, 0);
slotSpriteRound = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(681, 373, 58, 64), null, 0);
slotHotkeySprite = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(128, 0, 128, 128), null, 0);
EquipIndicator = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(673, 182, 73, 27), new Vector2(0.5f, 0.5f), 0);
EquipIndicatorHighlight = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(679, 108, 67, 21), new Vector2(0.5f, 0.5f), 0);
@@ -154,7 +158,7 @@ namespace Barotrauma
else
{
#if CLIENT
if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
#endif
return false;
}
@@ -280,11 +284,11 @@ namespace Barotrauma
{
for (int j = 0; j < capacity; j++)
{
if (Items[j] == item) slots[j].ShowBorderHighlight(Color.Green, 0.1f, 0.9f);
if (Items[j] == item) slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
}
for (int j = 0; j < otherInventory.capacity; j++)
{
if (otherInventory.Items[j] == existingItem) otherInventory.slots[j].ShowBorderHighlight(Color.Green, 0.1f, 0.9f);
if (otherInventory.Items[j] == existingItem) otherInventory.slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
}
}
#endif
@@ -322,7 +326,7 @@ namespace Barotrauma
{
if (Items[j] == existingItem)
{
slots[j].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
slots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
}
}
}
@@ -916,7 +916,7 @@ namespace Barotrauma
contained.Container = null;
}
public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true)
public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true, bool setPrevTransform = true)
{
if (!MathUtils.IsValid(simPosition))
{
@@ -938,13 +938,13 @@ namespace Barotrauma
try
{
#endif
if (body.Enabled)
if (body.PhysEnabled)
{
body.SetTransform(simPosition, rotation);
body.SetTransform(simPosition, rotation, setPrevTransform);
}
else
{
body.SetTransformIgnoreContacts(simPosition, rotation);
body.SetTransformIgnoreContacts(simPosition, rotation, setPrevTransform);
}
#if DEBUG
}
@@ -1270,10 +1270,6 @@ namespace Barotrauma
HandleCollision(impact);
}
if (!isActive) { return; }
aiTarget?.Update(deltaTime);
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
sendConditionUpdateTimer -= deltaTime;
@@ -1283,6 +1279,10 @@ namespace Barotrauma
}
}
if (!isActive) { return; }
aiTarget?.Update(deltaTime);
ApplyStatusEffects(ActionType.Always, deltaTime, character: (parentInventory as CharacterInventory)?.Owner as Character);
for (int i = 0; i < updateableComponents.Count; i++)
@@ -1376,7 +1376,7 @@ namespace Barotrauma
}
else
{
if (updateableComponents.Count == 0 && aiTarget == null && !conditionUpdatePending && !hasStatusEffectsOfType[(int)ActionType.Always] && body == null)
if (updateableComponents.Count == 0 && aiTarget == null && !hasStatusEffectsOfType[(int)ActionType.Always] && body == null)
{
#if CLIENT
positionBuffer.Clear();
@@ -1814,6 +1814,12 @@ namespace Barotrauma
else if (selected)
{
picker.SelectedConstruction = this;
#if CLIENT
if (GameMain.GameSession?.CrewManager != null && picker == Character.Controlled && GetComponent<Ladder>() == null)
{
GameMain.GameSession.CrewManager.ToggleCrewListOpen = false;
}
#endif
}
}
@@ -1823,7 +1829,7 @@ namespace Barotrauma
if (requiredSkill != null)
{
GUI.AddMessage(TextManager.GetWithVariables("InsufficientSkills", new string[2] { "[requiredskill]", "[requiredlevel]" },
new string[2] { TextManager.Get("SkillName." + requiredSkill.Identifier), ((int)requiredSkill.Level).ToString() }, new bool[2] { true, false }), Color.Red);
new string[2] { TextManager.Get("SkillName." + requiredSkill.Identifier), ((int)requiredSkill.Level).ToString() }, new bool[2] { true, false }), GUI.Style.Red);
}
}
#endif
@@ -14,6 +14,10 @@ namespace Barotrauma.Networking
private static Stream writeStream;
private static Stream readStream;
private static volatile bool shutDown;
public static bool HasShutDown
{
get { return shutDown; }
}
private static ManualResetEvent writeManualResetEvent;
private static byte[] tempBytes;
@@ -52,8 +56,16 @@ namespace Barotrauma.Networking
writeManualResetEvent = new ManualResetEvent(false);
readThread = new Thread(UpdateRead);
writeThread = new Thread(UpdateWrite);
readThread = new Thread(UpdateRead)
{
Name = "ChildServerRelay.ReadThread",
IsBackground = true
};
writeThread = new Thread(UpdateWrite)
{
Name = "ChildServerRelay.WriteThread",
IsBackground = true
};
readThread.Start();
writeThread.Start();
}
@@ -61,7 +73,7 @@ namespace Barotrauma.Networking
private static void PrivateShutDown()
{
shutDown = true;
writeManualResetEvent.Set();
writeManualResetEvent?.Set();
readCancellationToken?.Cancel();
readThread?.Join(); readThread = null;
writeThread?.Join(); writeThread = null;
@@ -76,8 +88,23 @@ namespace Barotrauma.Networking
while (!shutDown)
{
Task<int> readTask = readStream?.ReadAsync(tempBytes, 0, tempBytes.Length, readCancellationToken.Token);
TimeSpan ts = TimeSpan.FromMilliseconds(15000);
if (readTask == null || !readTask.Wait(ts))
TimeSpan ts = TimeSpan.FromMilliseconds(100);
for (int i=0;i<150;i++)
{
if (shutDown)
{
readCancellationToken?.Cancel();
shutDown = true;
return;
}
if ((readTask?.IsCompleted ?? true) || (readTask?.Wait(ts) ?? true))
{
break;
}
}
if (readTask == null || !readTask.IsCompleted)
{
readCancellationToken?.Cancel();
shutDown = true;
@@ -99,9 +126,12 @@ namespace Barotrauma.Networking
if (readState == ReadState.WaitingForPacketStart)
{
readIncTotal = tempBytes[procIndex] | (tempBytes[procIndex + 1] << 8);
procIndex += 2;
if (readIncTotal <= 0) { continue; }
readIncOffset = 0;
readIncBuf = new byte[readIncTotal];
procIndex += 2;
readState = ReadState.WaitingForPacketEnd;
}
else if (readState == ReadState.WaitingForPacketEnd)
@@ -159,7 +189,14 @@ namespace Barotrauma.Networking
if (!shutDown)
{
writeManualResetEvent.Reset();
writeManualResetEvent.WaitOne();
if (!writeManualResetEvent.WaitOne(1000))
{
//heartbeat to keep the other end alive
byte[] lengthBytes = new byte[2];
lengthBytes[0] = (byte)0;
lengthBytes[1] = (byte)0;
writeStream?.Write(lengthBytes, 0, 2);
}
}
}
}
@@ -291,8 +291,8 @@ namespace Barotrauma.Networking
Port = port;
QueryPort = queryPort;
EnableUPnP = enableUPnP;
this.maxPlayers = maxPlayers;
this.isPublic = isPublic;
MaxPlayers = maxPlayers;
IsPublic = isPublic;
netProperties = new Dictionary<UInt32, NetPropertyData>();
@@ -376,7 +376,7 @@ namespace Barotrauma.Networking
private bool autoRestart;
public bool isPublic;
public bool IsPublic;
private int maxPlayers;
@@ -810,6 +810,7 @@ namespace Barotrauma.Networking
set;
}
[Serialize(8, true)]
public int MaxPlayers
{
get { return maxPlayers; }
@@ -648,17 +648,14 @@ namespace Barotrauma
Vector2 velocityAddition = force / Mass * (float)Timing.Step;
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
float newSpeedSqr = newVelocity.LengthSquared();
if (newSpeedSqr > maxVelocity * maxVelocity)
if (newSpeedSqr > maxVelocity * maxVelocity && Vector2.Dot(body.LinearVelocity, force) > 0.0f)
{
float velSqr = body.LinearVelocity.LengthSquared();
if (newSpeedSqr > velSqr)
{
if (velSqr > maxVelocity * maxVelocity) { return; }
newVelocity = newVelocity.ClampLength(maxVelocity);
force = (newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step;
}
float newSpeed = (float)Math.Sqrt(newSpeedSqr);
float maxVelAddition = maxVelocity - newSpeed;
if (maxVelAddition <= 0.0f) { return; }
force = velocityAddition.ClampLength(maxVelAddition) * Mass / (float)Timing.Step;
}
if (!IsValidValue(force, "clamped force", -1e10f, 1e10f)) return;
@@ -678,7 +675,7 @@ namespace Barotrauma
body.ApplyTorque(torque);
}
public bool SetTransform(Vector2 simPosition, float rotation)
public bool SetTransform(Vector2 simPosition, float rotation, bool setPrevTransform = true)
{
System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition));
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f);
@@ -688,11 +685,11 @@ namespace Barotrauma
if (!IsValidValue(rotation, "rotation")) return false;
body.SetTransform(simPosition, rotation);
SetPrevTransform(simPosition, rotation);
if (setPrevTransform) { SetPrevTransform(simPosition, rotation); }
return true;
}
public bool SetTransformIgnoreContacts(Vector2 simPosition, float rotation)
public bool SetTransformIgnoreContacts(Vector2 simPosition, float rotation, bool setPrevTransform = true)
{
System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition));
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f);
@@ -702,7 +699,7 @@ namespace Barotrauma
if (!IsValidValue(rotation, "rotation")) return false;
body.SetTransformIgnoreContacts(ref simPosition, rotation);
SetPrevTransform(simPosition, rotation);
if (setPrevTransform) { SetPrevTransform(simPosition, rotation); }
return true;
}
@@ -178,11 +178,20 @@ namespace Barotrauma
Lights.LightManager.ViewTarget != null)
{
Vector2 targetPos = Lights.LightManager.ViewTarget.DrawPosition;
if (Lights.LightManager.ViewTarget == Character.Controlled && CharacterHealth.OpenHealthWindow != null)
if (Lights.LightManager.ViewTarget == Character.Controlled &&
(CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen))
{
Vector2 screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ?
new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) :
new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f);
Vector2 screenTargetPos = new Vector2(0.0f, GameMain.GraphicsHeight * 0.5f);
if (CrewManager.IsCommandInterfaceOpen)
{
screenTargetPos.X = GameMain.GraphicsWidth * 0.5f;
}
else
{
screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ?
new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) :
new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f);
}
Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2);
screenOffset.Y = -screenOffset.Y;
targetPos -= screenOffset / cam.Zoom;
@@ -399,6 +399,31 @@ namespace Barotrauma
return ParseColor(element.Attribute(name).Value);
}
public static Color[] GetAttributeColorArray(this XElement element, string name, Color[] defaultValue)
{
if (element?.Attribute(name) == null) return defaultValue;
string stringValue = element.Attribute(name).Value;
if (string.IsNullOrEmpty(stringValue)) return defaultValue;
string[] splitValue = stringValue.Split(';');
Color[] colorValue = new Color[splitValue.Length];
for (int i = 0; i < splitValue.Length; i++)
{
try
{
Color val = ParseColor(splitValue[i], true);
colorValue[i] = val;
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in " + element + "! ", e);
}
}
return colorValue;
}
public static Rectangle GetAttributeRect(this XElement element, string name, Rectangle defaultValue)
{
if (element == null || element.Attribute(name) == null) return defaultValue;
@@ -102,6 +102,8 @@ namespace Barotrauma
}
}
public Vector2 RelativeSize { get; private set; }
public string FilePath { get; private set; }
public string FullPath { get; private set; }
@@ -132,6 +134,7 @@ namespace Barotrauma
public Sprite(XElement element, string path = "", string file = "", bool lazyLoad = false)
{
if (element == null) { return; }
this.lazyLoad = lazyLoad;
SourceElement = element;
if (!ParseTexturePath(path, file)) { return; }
@@ -150,6 +153,7 @@ namespace Barotrauma
if (shouldReturn) { return; }
sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W);
size = SourceElement.GetAttributeVector2("size", Vector2.One);
RelativeSize = size;
size.X *= sourceRect.Width;
size.Y *= sourceRect.Height;
RelativeOrigin = SourceElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f));
@@ -55,6 +55,26 @@ namespace Barotrauma
MathHelper.SmoothStep(v1.Y, v2.Y, amount));
}
public static float SmoothStep(float t)
{
return t * t * (3f - 2f * t);
}
public static float SmootherStep(float t)
{
return t * t * t * (t * (6f * t - 15f) + 10f);
}
public static float EaseIn(float t)
{
return 1f - (float)Math.Cos(t * MathHelper.PiOver2);
}
public static float EaseOut(float t)
{
return (float)Math.Sin(t * MathHelper.PiOver2);
}
public static Vector2 ClampLength(this Vector2 v, float length)
{
float currLength = v.Length();
@@ -530,6 +550,42 @@ namespace Barotrauma
return distSqX * distSqX + distSqY * distSqY <= radius * radius;
}
/// <summary>
/// Get a point on a circle's circumference
/// </summary>
/// <param name="center">Center of the circle</param>
/// <param name="radius">Radius of the circle</param>
/// <param name="angle">Angle (in radians) from the center</param>
/// <returns></returns>
public static Vector2 GetPointOnCircumference(Vector2 center, float radius, float angle)
{
return new Vector2(
center.X + radius * (float)Math.Cos(angle),
center.Y + radius * (float)Math.Sin(angle));
}
/// <summary>
/// Get a specific number of evenly distributed points on a circle's circumference
/// </summary>
/// <param name="center">Center of the circle</param>
/// <param name="radius">Radius of the circle</param>
/// <param name="points">Number of points to calculate</param>
/// <param name="firstAngle">Angle (in radians) of the first point from the center</param>
/// <returns></returns>
public static Vector2[] GetPointsOnCircumference(Vector2 center, float radius, int points, float firstAngle = 0.0f)
{
var maxAngle = (float)(2 * Math.PI);
var angleStep = maxAngle / points;
var coordinates = new Vector2[points];
for (int i = 0; i < points; i++)
{
var angle = firstAngle + (i * angleStep);
if (angle > maxAngle) { angle -= maxAngle; }
coordinates[i] = GetPointOnCircumference(center, radius, angle);
}
return coordinates;
}
/// <summary>
/// divide a convex hull into triangles
/// </summary>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+26
View File
@@ -1,3 +1,29 @@
---------------------------------------------------------------------------------------------------------
v0.9.702 (Unstable)
---------------------------------------------------------------------------------------------------------
- UI overhaul
- Increased level sizes.
- Rebalanced monster spawns.
- Added a few new artifact missions.
- Fixed server not sending condition updates for inactive items, potentially causing the condition to get desynced when all of the components of the item go inactive.
- Fixed clients being unable to rejoin a SteamP2P server after they've left.
- Fix to inventory items occasionally getting mixed up in the campaign.
- Power consumption of damaged devices doesn't increase as much anymore.
- Player cap can be adjusted in the server settings.
- Fixed "cannot remove joints when the world is locked" error message when a character latched onto the sub is attacked.
- Fixed currents heavily slowing down the submarine regardless of the force or direction of the current.
- Improved name tag hiding.
- Fixed explosives that disappear after exploding (e.g. nuclear explosives) not playing the explosion sound.
- Fixed server list not listing passworded SteamP2P servers correctly.
- Reduced Daedalic splash screen volume further!
- Made tonic liquid purchasable.
- Subscribed Workshop items aren't shown in the Popular tab.
- Fixed some held items vibrating/twitching when moving.
- Fixed turrets emitting muzzle flash particles in an incorrect direction (the rotation of the particle was correct but the direction it flied towards not, which isn't noticeable with the non-moving vanilla particles).
- Fixed clients not relaying console commands that don't exist client-side to the server (i.e. custom commands implemented by a server mod can now be used by clients).
- Added combat priorities to alien weapons to allow bots to use them.
---------------------------------------------------------------------------------------------------------
v0.9.701 (Unstable)
---------------------------------------------------------------------------------------------------------
@@ -43,6 +43,7 @@
public="false"
port="27015"
queryport="27016"
playstyle="Casual"
maxplayers="10"
enableupnp="false"
autorestart="false"