v0.10.5.1

This commit is contained in:
Juan Pablo Arce
2020-09-22 11:31:56 -03:00
parent 44032d0ae0
commit 0002ad2c50
343 changed files with 12276 additions and 5023 deletions
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
namespace Barotrauma
@@ -11,28 +13,39 @@ namespace Barotrauma
public readonly DelayedEffect Parent;
public readonly Entity Entity;
public readonly Vector2? WorldPosition;
public readonly Vector2? StartPosition;
public readonly List<ISerializableEntity> Targets;
public float StartTimer;
public float Delay;
public DelayedListElement(DelayedEffect parentEffect, Entity parentEntity, IEnumerable<ISerializableEntity> targets, float delay, Vector2? worldPosition)
public DelayedListElement(DelayedEffect parentEffect, Entity parentEntity, IEnumerable<ISerializableEntity> targets, float delay, Vector2? worldPosition, Vector2? startPosition)
{
Parent = parentEffect;
Entity = parentEntity;
Targets = new List<ISerializableEntity>(targets);
StartTimer = delay;
Delay = delay;
WorldPosition = worldPosition;
StartPosition = startPosition;
}
}
class DelayedEffect : StatusEffect
{
public static readonly List<DelayedListElement> DelayList = new List<DelayedListElement>();
private enum DelayTypes { timer = 0, reachcursor = 1 }
private DelayTypes delayType;
private float delay;
public DelayedEffect(XElement element, string parentDebugName)
: base(element, parentDebugName)
{
delay = element.GetAttributeFloat("delay", 1.0f);
delayType = (DelayTypes)Enum.Parse(typeof(DelayTypes), element.GetAttributeString("delaytype", "timer"));
switch (delayType)
{
case DelayTypes.timer:
delay = element.GetAttributeFloat("delay", 1.0f);
break;
}
}
public override void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target, Vector2? worldPosition = null)
@@ -42,14 +55,36 @@ namespace Barotrauma
if (targetIdentifiers != null && !IsValidTarget(target)) { return; }
if (!HasRequiredConditions(target.ToEnumerable())) { return; }
DelayList.Add(new DelayedListElement(this, entity, target.ToEnumerable(), delay, worldPosition));
switch (delayType)
{
case DelayTypes.timer:
DelayList.Add(new DelayedListElement(this, entity, target.ToEnumerable(), delay, worldPosition, null));
break;
case DelayTypes.reachcursor:
Projectile projectile = (entity as Item)?.GetComponent<Projectile>();
if (projectile == null)
{
DebugConsole.NewMessage("Non-projectile using a delaytype of reachcursor", Color.Red, false, true);
return;
}
if (projectile.User == null)
{
DebugConsole.NewMessage("Projectile: '" + projectile.Name + "' missing user to determine distance", Color.Red, false, true);
return;
}
DelayList.Add(new DelayedListElement(this, entity, target.ToEnumerable(), Vector2.Distance(entity.WorldPosition, projectile.User.CursorWorldPosition), worldPosition, entity.WorldPosition));
break;
}
}
public override void Apply(ActionType type, float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Vector2? worldPosition = null)
{
if (this.type != type || !HasRequiredItems(entity)) { return; }
if (!Stackable && DelayList.Any(d => d.Parent == this && d.Targets.SequenceEqual(targets))) { return; }
if (delayType == DelayTypes.reachcursor && Character.Controlled == null) return;
currentTargets.Clear();
foreach (ISerializableEntity target in targets)
{
@@ -63,7 +98,32 @@ namespace Barotrauma
if (!HasRequiredConditions(currentTargets)) { return; }
DelayList.Add(new DelayedListElement(this, entity, currentTargets, delay, worldPosition));
switch (delayType)
{
case DelayTypes.timer:
DelayList.Add(new DelayedListElement(this, entity, targets, delay, worldPosition, null));
break;
case DelayTypes.reachcursor:
Projectile projectile = (entity as Item)?.GetComponent<Projectile>();
if (projectile == null)
{
#if DEBUG
DebugConsole.NewMessage("Non-projectile using a delaytype of reachcursor", Color.Red, false, true);
#endif
return;
}
if (projectile.User == null)
{
#if DEBUG
DebugConsole.NewMessage("Projectile " + projectile.Name + "missing user", Color.Red, false, true);
#endif
return;
}
DelayList.Add(new DelayedListElement(this, entity, targets, Vector2.Distance(entity.WorldPosition, projectile.User.CursorWorldPosition), worldPosition, entity.WorldPosition));
break;
}
}
public static void Update(float deltaTime)
@@ -77,9 +137,16 @@ namespace Barotrauma
continue;
}
element.StartTimer -= deltaTime;
if (element.StartTimer > 0.0f) { continue; }
switch (element.Parent.delayType)
{
case DelayTypes.timer:
element.Delay -= deltaTime;
if (element.Delay > 0.0f) { continue; }
break;
case DelayTypes.reachcursor:
if (Vector2.Distance(element.Entity.WorldPosition, element.StartPosition.Value) < element.Delay) continue;
break;
}
element.Parent.Apply(deltaTime, element.Entity, element.Targets, element.WorldPosition);
DelayList.Remove(element);
@@ -12,6 +12,11 @@ namespace Barotrauma
{
public readonly StatusEffect Parent;
public readonly Entity Entity;
public float Duration
{
get;
private set;
}
public readonly List<ISerializableEntity> Targets;
public Character User { get; private set; }
@@ -22,13 +27,13 @@ namespace Barotrauma
Parent = parentEffect;
Entity = parentEntity;
Targets = new List<ISerializableEntity>(targets);
Timer = duration;
Timer = Duration = duration;
User = user;
}
public void Reset(float duration, Character newUser)
{
Timer = duration;
Timer = Duration = duration;
User = newUser;
}
}
@@ -126,7 +131,7 @@ namespace Barotrauma
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
if (string.IsNullOrEmpty(SpeciesName))
{
DebugConsole.ThrowError($"Invalid character spawn ({Name}) in StatusEffect \"{parentDebugName}\" - identifier not found in the element \"{element.ToString()}\"");
DebugConsole.ThrowError($"Invalid character spawn ({Name}) in StatusEffect \"{parentDebugName}\" - identifier not found in the element \"{element}\"");
}
}
}
@@ -165,7 +170,7 @@ namespace Barotrauma
public readonly ActionType type = ActionType.OnActive;
private readonly Explosion explosion;
private readonly List<Explosion> explosions;
private readonly List<ItemSpawnInfo> spawnItems;
private readonly List<CharacterSpawnInfo> spawnCharacters;
@@ -224,7 +229,7 @@ namespace Barotrauma
public static StatusEffect Load(XElement element, string parentDebugName)
{
if (element.Attribute("delay") != null)
if (element.Attribute("delay") != null || element.Attribute("delaytype") != null)
{
return new DelayedEffect(element, parentDebugName);
}
@@ -238,6 +243,7 @@ namespace Barotrauma
spawnItems = new List<ItemSpawnInfo>();
spawnCharacters = new List<CharacterSpawnInfo>();
Afflictions = new List<Affliction>();
explosions = new List<Explosion>();
reduceAffliction = new List<Pair<string, float>>();
tags = new HashSet<string>(element.GetAttributeString("tags", "").Split(','));
@@ -351,7 +357,7 @@ namespace Barotrauma
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "explosion":
explosion = new Explosion(subElement, parentDebugName);
explosions.Add(new Explosion(subElement, parentDebugName));
break;
case "fire":
FireSize = subElement.GetAttributeFloat("size", 10.0f);
@@ -600,28 +606,28 @@ namespace Barotrauma
if (entity is Item item)
{
if (targetIdentifiers.Contains("item")) return true;
if (item.HasTag(targetIdentifiers)) return true;
if (targetIdentifiers.Any(id => id == item.Prefab.Identifier)) return true;
if (targetIdentifiers.Contains("item")) { return true; }
if (item.HasTag(targetIdentifiers)) { return true; }
if (targetIdentifiers.Any(id => id.Equals(item.Prefab.Identifier, StringComparison.OrdinalIgnoreCase))) { return true; }
}
else if (entity is ItemComponent itemComponent)
{
if (targetIdentifiers.Contains("itemcomponent")) return true;
if (itemComponent.Item.HasTag(targetIdentifiers)) return true;
if (targetIdentifiers.Any(id => id == itemComponent.Item.Prefab.Identifier)) return true;
if (targetIdentifiers.Contains("itemcomponent")) { return true; }
if (itemComponent.Item.HasTag(targetIdentifiers)) { return true; }
if (targetIdentifiers.Any(id => id.Equals(itemComponent.Item.Prefab.Identifier, StringComparison.OrdinalIgnoreCase))) { return true; }
}
else if (entity is Structure structure)
{
if (targetIdentifiers.Contains("structure")) return true;
if (targetIdentifiers.Any(id => id == structure.Prefab.Identifier)) return true;
if (targetIdentifiers.Contains("structure")) { return true; }
if (targetIdentifiers.Any(id => id.Equals(structure.Prefab.Identifier, StringComparison.OrdinalIgnoreCase))) { return true; }
}
else if (entity is Character character)
{
if (targetIdentifiers.Contains("character")) return true;
if (targetIdentifiers.Any(id => id == character.SpeciesName)) return true;
if (targetIdentifiers.Contains("character")) { return true; }
if (targetIdentifiers.Any(id => id.Equals(character.SpeciesName, StringComparison.OrdinalIgnoreCase))) { return true; }
}
return targetIdentifiers.Any(id => id == entity.Name);
return targetIdentifiers.Any(id => id.Equals(entity.Name, StringComparison.OrdinalIgnoreCase));
}
public void SetUser(Character user)
@@ -688,6 +694,46 @@ namespace Barotrauma
Apply(deltaTime, entity, currentTargets, worldPosition);
}
private Hull GetHull(Entity entity)
{
Hull hull = null;
if (entity is Character character)
{
hull = character.AnimController.CurrentHull;
}
else if (entity is Item item)
{
hull = item.CurrentHull;
}
return hull;
}
private Vector2 GetPosition(Entity entity, IEnumerable<ISerializableEntity> targets, Vector2? worldPosition = null)
{
Vector2 position = worldPosition ?? (entity.Removed ? Vector2.Zero : entity.WorldPosition);
if (worldPosition == null)
{
if (entity is Character c && targetLimbs?.FirstOrDefault(l => l != LimbType.None) is LimbType l)
{
Limb limb = c.AnimController.GetLimb(l);
if (limb != null && !limb.Removed)
{
position = limb.WorldPosition;
}
}
else
{
var targetLimb = targets.FirstOrDefault(t => t is Limb) as Limb;
if (targetLimb != null && !targetLimb.Removed)
{
position = targetLimb.WorldPosition;
}
}
}
position += Offset;
return position;
}
protected void Apply(float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Vector2? worldPosition = null)
{
if (lifeTime > 0)
@@ -696,30 +742,8 @@ namespace Barotrauma
if (lifeTimer <= 0) { return; }
}
Hull hull = null;
if (entity is Character)
{
hull = ((Character)entity).AnimController.CurrentHull;
}
else if (entity is Item)
{
hull = ((Item)entity).CurrentHull;
}
Vector2 position = worldPosition ?? (entity.Removed ? Vector2.Zero : entity.WorldPosition);
if (worldPosition == null && targetLimbs?.FirstOrDefault(l => l != LimbType.None) is LimbType l)
{
if (entity is Character c)
{
Limb limb = c.AnimController.GetLimb(l);
if (limb != null && !limb.Removed)
{
position = limb.WorldPosition;
}
}
}
position += Offset;
Hull hull = GetHull(entity);
Vector2 position = GetPosition(entity, targets, worldPosition);
foreach (ISerializableEntity serializableEntity in targets)
{
if (!(serializableEntity is Item item)) { continue; }
@@ -783,9 +807,12 @@ namespace Barotrauma
}
}
if (explosion != null && entity != null)
if (entity != null)
{
explosion.Explode(position, damageSource: entity, attacker: user);
foreach (Explosion explosion in explosions)
{
explosion.Explode(position, damageSource: entity, attacker: user);
}
}
foreach (ISerializableEntity target in targets)
@@ -888,9 +915,10 @@ namespace Barotrauma
break;
case ItemSpawnInfo.SpawnPositionType.ThisInventory:
{
if (entity is Character character)
if (entity is Character character && character.Inventory != null)
{
if (character.Inventory != null && character.Inventory.Items.Any(it => it == null))
int emptyCount = character.Inventory.Items.Count(it => it == null);
if (emptyCount - Entity.Spawner.CountSpawnQueue(spawnInfo => spawnInfo is EntitySpawner.ItemSpawnInfo itemSpawnInfo && itemSpawnInfo.Inventory == character.Inventory) > 0)
{
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, character.Inventory);
}
@@ -898,9 +926,13 @@ namespace Barotrauma
else if (entity is Item item)
{
var inventory = item?.GetComponent<ItemContainer>()?.Inventory;
if (inventory != null && inventory.Items.Any(it => it == null))
if (inventory != null)
{
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
int emptyCount = inventory.Items.Count(it => it == null);
if (emptyCount - Entity.Spawner.CountSpawnQueue(spawnInfo => spawnInfo is EntitySpawner.ItemSpawnInfo itemSpawnInfo && itemSpawnInfo.Inventory == inventory) > 0)
{
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
}
}
}
}
@@ -933,10 +965,10 @@ namespace Barotrauma
}
}
ApplyProjSpecific(deltaTime, entity, targets, hull, position);
ApplyProjSpecific(deltaTime, entity, targets, hull, position, playSound: true);
}
partial void ApplyProjSpecific(float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Hull currentHull, Vector2 worldPosition);
partial void ApplyProjSpecific(float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Hull currentHull, Vector2 worldPosition, bool playSound);
private void ApplyToProperty(ISerializableEntity target, SerializableProperty property, object value, float deltaTime)
{
@@ -1060,6 +1092,13 @@ namespace Barotrauma
}
}
element.Parent.ApplyProjSpecific(deltaTime,
element.Entity,
element.Targets,
element.Parent.GetHull(element.Entity),
element.Parent.GetPosition(element.Entity, element.Targets),
playSound: element.Timer >= element.Duration);
element.Timer -= deltaTime;
if (element.Timer > 0.0f) { continue; }