(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
@@ -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);