(3dc4135ce) v0.9.5.1

This commit is contained in:
Regalis
2019-11-21 18:22:25 +01:00
parent b39922a074
commit 5c95c53118
287 changed files with 12655 additions and 5048 deletions
@@ -87,6 +87,27 @@ namespace Barotrauma
}
}
class CharacterSpawnInfo : ISerializableEntity
{
public string Name => $"Character Spawn Info ({SpeciesName})";
public Dictionary<string, SerializableProperty> SerializableProperties { get; set; }
[Serialize("", false)]
public string SpeciesName { get; private set; }
[Serialize(1, false)]
public int Count { get; private set; }
[Serialize(0f, false)]
public float Spread { get; private set; }
public CharacterSpawnInfo(XElement element, string parentDebugName)
{
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()}\"");
}
}
}
private TargetType targetTypes;
protected HashSet<string> targetIdentifiers;
@@ -106,6 +127,9 @@ namespace Barotrauma
private HashSet<string> tags;
private readonly float duration;
private readonly float lifeTime;
private float lifeTimer;
public static readonly List<DurationListElement> DurationList = new List<DurationListElement>();
public bool CheckConditionalAlways; //Always do the conditional checks for the duration/delay. If false, only check conditional on apply.
@@ -114,17 +138,20 @@ namespace Barotrauma
private readonly int useItemCount;
private readonly bool removeItem;
private readonly bool removeItem, removeCharacter;
public readonly ActionType type = ActionType.OnActive;
private Explosion explosion;
private readonly Explosion explosion;
private List<ItemSpawnInfo> spawnItems;
private List<CharacterSpawnInfo> spawnCharacters;
private Character user;
public readonly float FireSize;
public readonly LimbType targetLimb;
public readonly float SeverLimbsProbability;
@@ -180,11 +207,17 @@ namespace Barotrauma
{
requiredItems = new List<RelatedItem>();
spawnItems = new List<ItemSpawnInfo>();
spawnCharacters = new List<CharacterSpawnInfo>();
Afflictions = new List<Affliction>();
ReduceAffliction = new List<Pair<string, float>>();
tags = new HashSet<string>(element.GetAttributeString("tags", "").Split(','));
Range = element.GetAttributeFloat("range", 0.0f);
string targetLimbName = element.GetAttributeString("targetlimb", null);
if (targetLimbName != null)
{
Enum.TryParse(targetLimbName, out targetLimb);
}
IEnumerable<XAttribute> attributes = element.Attributes();
List<XAttribute> propertyAttributes = new List<XAttribute>();
@@ -242,6 +275,10 @@ namespace Barotrauma
case "stackable":
Stackable = attribute.GetAttributeBool(true);
break;
case "lifetime":
lifeTime = attribute.GetAttributeFloat(0);
lifeTimer = lifeTime;
break;
case "checkconditionalalways":
CheckConditionalAlways = attribute.GetAttributeBool(false);
break;
@@ -292,9 +329,12 @@ namespace Barotrauma
case "removeitem":
removeItem = true;
break;
case "removecharacter":
removeCharacter = true;
break;
case "requireditem":
case "requireditems":
RelatedItem newRequiredItem = RelatedItem.Load(subElement, parentDebugName);
RelatedItem newRequiredItem = RelatedItem.Load(subElement, returnEmpty: false, parentDebugName: parentDebugName);
if (newRequiredItem == null)
{
DebugConsole.ThrowError("Error in StatusEffect config - requires an item with no identifiers.");
@@ -365,7 +405,11 @@ namespace Barotrauma
break;
case "spawnitem":
var newSpawnItem = new ItemSpawnInfo(subElement, parentDebugName);
if (newSpawnItem.ItemPrefab != null) spawnItems.Add(newSpawnItem);
if (newSpawnItem.ItemPrefab != null) { spawnItems.Add(newSpawnItem); }
break;
case "spawncharacter":
var newSpawnCharacter = new CharacterSpawnInfo(subElement, parentDebugName);
if (!string.IsNullOrWhiteSpace(newSpawnCharacter.SpeciesName)) { spawnCharacters.Add(newSpawnCharacter); }
break;
}
}
@@ -433,8 +477,8 @@ namespace Barotrauma
public virtual bool HasRequiredConditions(List<ISerializableEntity> targets)
{
if (!propertyConditionals.Any()) return true;
if (requiredItems.All(ri => ri.MatchOnEmpty) && targets.Count == 0) return true;
if (!propertyConditionals.Any()) { return true; }
if (requiredItems.Any() && requiredItems.All(ri => ri.MatchOnEmpty) && targets.Count == 0) { return true; }
switch (conditionalComparison)
{
case PropertyConditional.Comparison.Or:
@@ -513,7 +557,7 @@ namespace Barotrauma
}
}
public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target)
public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target, Vector2? worldPosition = null)
{
if (this.type != type || !HasRequiredItems(entity)) return;
@@ -535,11 +579,11 @@ namespace Barotrauma
if (!HasRequiredConditions(targets)) return;
Apply(deltaTime, entity, targets);
Apply(deltaTime, entity, targets, worldPosition);
}
protected readonly List<ISerializableEntity> currentTargets = new List<ISerializableEntity>();
public virtual void Apply(ActionType type, float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets)
public virtual void Apply(ActionType type, float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets, Vector2? worldPosition = null)
{
if (this.type != type) return;
@@ -570,11 +614,17 @@ namespace Barotrauma
}
}
Apply(deltaTime, entity, currentTargets);
Apply(deltaTime, entity, currentTargets, worldPosition);
}
protected void Apply(float deltaTime, Entity entity, List<ISerializableEntity> targets)
protected void Apply(float deltaTime, Entity entity, List<ISerializableEntity> targets, Vector2? worldPosition = null)
{
if (lifeTime > 0)
{
lifeTimer -= deltaTime;
if (lifeTimer <= 0) { return; }
}
Hull hull = null;
if (entity is Character)
{
@@ -585,9 +635,22 @@ namespace Barotrauma
hull = ((Item)entity).CurrentHull;
}
Vector2 position = worldPosition ?? entity.WorldPosition;
if (targetLimb != LimbType.None)
{
if (entity is Character c)
{
Limb limb = c.AnimController.GetLimb(targetLimb);
if (limb != null)
{
position = limb.WorldPosition;
}
}
}
foreach (ISerializableEntity serializableEntity in targets)
{
if (!(serializableEntity is Item item)) continue;
if (!(serializableEntity is Item item)) { continue; }
Character targetCharacter = targets.FirstOrDefault(t => t is Character character && !character.Removed) as Character;
if (targetCharacter == null)
@@ -606,9 +669,16 @@ namespace Barotrauma
if (removeItem)
{
foreach (Item item in targets.Where(t => t is Item).Cast<Item>())
foreach (var target in targets)
{
Entity.Spawner?.AddToRemoveQueue(item);
if (target is Item item) { Entity.Spawner?.AddToRemoveQueue(item); }
}
}
if (removeCharacter)
{
foreach (var target in targets)
{
if (target is Character character) { Entity.Spawner?.AddToRemoveQueue(character); }
}
}
@@ -643,7 +713,10 @@ namespace Barotrauma
}
}
if (explosion != null && entity != null) { explosion.Explode(entity.WorldPosition, damageSource: entity, attacker: user); }
if (explosion != null && entity != null)
{
explosion.Explode(position, damageSource: entity, attacker: user);
}
foreach (ISerializableEntity target in targets)
{
@@ -658,7 +731,7 @@ namespace Barotrauma
character.LastDamageSource = entity;
foreach (Limb limb in character.AnimController.Limbs)
{
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
limb.character.DamageLimb(position, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
limb.character.TrySeverLimbJoints(limb, SeverLimbsProbability);
//only apply non-limb-specific afflictions to the first limb
if (!affliction.Prefab.LimbSpecific) { break; }
@@ -667,7 +740,7 @@ namespace Barotrauma
else if (target is Limb limb)
{
if (limb.character.Removed) { continue; }
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
limb.character.DamageLimb(position, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f, attacker: affliction.Source);
limb.character.TrySeverLimbJoints(limb, SeverLimbsProbability);
}
}
@@ -694,25 +767,40 @@ namespace Barotrauma
GameMain.Server.KarmaManager.OnCharacterHealthChanged(targetCharacter, user, prevVitality - targetCharacter.Vitality);
#endif
}
}
}
if (FireSize > 0.0f && entity != null)
{
var fire = new FireSource(entity.WorldPosition, hull);
var fire = new FireSource(position, hull);
fire.Size = new Vector2(FireSize, fire.Size.Y);
}
bool isNotClient = GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient;
if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn entities
{
foreach (CharacterSpawnInfo characterSpawnInfo in spawnCharacters)
{
var characters = new List<Character>();
for (int i = 0; i < characterSpawnInfo.Count; i++)
{
Entity.Spawner.AddToSpawnQueue(characterSpawnInfo.SpeciesName, position + Rand.Vector(characterSpawnInfo.Spread, Rand.RandSync.Server),
onSpawn: newCharacter =>
{
characters.Add(newCharacter);
if (characters.Count == characterSpawnInfo.Count)
{
SwarmBehavior.CreateSwarm(characters.Cast<AICharacter>());
}
});
}
}
foreach (ItemSpawnInfo itemSpawnInfo in spawnItems)
{
switch (itemSpawnInfo.SpawnPosition)
{
case ItemSpawnInfo.SpawnPositionType.This:
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, entity.WorldPosition);
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, position);
break;
case ItemSpawnInfo.SpawnPositionType.ThisInventory:
{
@@ -761,10 +849,10 @@ namespace Barotrauma
}
}
ApplyProjSpecific(deltaTime, entity, targets, hull);
ApplyProjSpecific(deltaTime, entity, targets, hull, position);
}
partial void ApplyProjSpecific(float deltaTime, Entity entity, List<ISerializableEntity> targets, Hull currentHull);
partial void ApplyProjSpecific(float deltaTime, Entity entity, List<ISerializableEntity> targets, Hull currentHull, Vector2 worldPosition);
private void ApplyToProperty(ISerializableEntity target, SerializableProperty property, object value, float deltaTime)
{