2f107db...5202af9

This commit is contained in:
Joonas Rikkonen
2019-03-18 21:42:26 +02:00
parent 58c92888b7
commit 044fd3344b
395 changed files with 27417 additions and 19754 deletions
@@ -107,6 +107,7 @@ namespace Barotrauma
public string[] propertyNames;
private object[] propertyEffects;
private PropertyConditional.Comparison conditionalComparison = PropertyConditional.Comparison.And;
private List<PropertyConditional> propertyConditionals;
private bool setValue;
@@ -205,12 +206,7 @@ namespace Barotrauma
switch (attribute.Name.ToString())
{
case "type":
try
{
type = (ActionType)Enum.Parse(typeof(ActionType), attribute.Value, true);
}
catch
if (!Enum.TryParse(attribute.Value, true, out type))
{
DebugConsole.ThrowError("Invalid action type \"" + attribute.Value + "\" in StatusEffect (" + parentDebugName + ")");
}
@@ -219,9 +215,15 @@ namespace Barotrauma
string[] Flags = attribute.Value.Split(',');
foreach (string s in Flags)
{
targetTypes |= (TargetType)Enum.Parse(typeof(TargetType), s, true);
if (!Enum.TryParse(s, true, out TargetType targetType))
{
DebugConsole.ThrowError("Invalid target type \"" + s + "\" in StatusEffect (" + parentDebugName + ")");
}
else
{
targetTypes |= targetType;
}
}
break;
case "disabledeltatime":
disableDeltaTime = attribute.GetAttributeBool(false);
@@ -249,6 +251,13 @@ namespace Barotrauma
case "checkconditionalalways":
CheckConditionalAlways = attribute.GetAttributeBool(false);
break;
case "conditionalcomparison":
case "comparison":
if (!Enum.TryParse(attribute.Value, out conditionalComparison))
{
DebugConsole.ThrowError("Invalid conditional comparison type \"" + attribute.Value + "\" in StatusEffect (" + parentDebugName + ")");
}
break;
case "sound":
DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() +
" - sounds should be defined as child elements of the StatusEffect, not as attributes.");
@@ -370,16 +379,18 @@ namespace Barotrauma
break;
case "sound":
var sound = Submarine.LoadRoundSound(subElement);
loopSound = subElement.GetAttributeBool("loop", false);
if (subElement.Attribute("selectionmode") != null)
if (sound != null)
{
if (Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode))
loopSound = subElement.GetAttributeBool("loop", false);
if (subElement.Attribute("selectionmode") != null)
{
soundSelectionMode = selectionMode;
if (Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode))
{
soundSelectionMode = selectionMode;
}
}
sounds.Add(sound);
}
sounds.Add(sound);
break;
#endif
}
@@ -419,7 +430,7 @@ namespace Barotrauma
{
foreach (Character c in Character.CharacterList)
{
if (!c.Enabled) { continue; }
if (!c.Enabled || c.Removed || !IsValidTarget(c)) { continue; }
float xDiff = Math.Abs(c.WorldPosition.X - worldPosition.X);
if (xDiff > Range) { continue; }
float yDiff = Math.Abs(c.WorldPosition.Y - worldPosition.Y);
@@ -432,6 +443,7 @@ namespace Barotrauma
{
foreach (Item item in Item.ItemList)
{
if (item.Removed || !IsValidTarget(item)) { continue; }
float xDiff = Math.Abs(item.WorldPosition.X - worldPosition.X);
if (xDiff > Range) { continue; }
float yDiff = Math.Abs(item.WorldPosition.Y - worldPosition.Y);
@@ -440,21 +452,68 @@ namespace Barotrauma
if (xDiff * xDiff + yDiff * yDiff < Range * Range) { targets.Add(item); }
}
}
return;
}
public virtual bool HasRequiredConditions(List<ISerializableEntity> targets)
{
if (!propertyConditionals.Any()) return true;
foreach (ISerializableEntity target in targets)
switch (conditionalComparison)
{
if (target == null || target.SerializableProperties == null) continue;
foreach (PropertyConditional pc in propertyConditionals)
{
if (pc.Matches(target)) return true;
}
case PropertyConditional.Comparison.Or:
foreach (ISerializableEntity target in targets)
{
if (target == null || target.SerializableProperties == null) { continue; }
foreach (PropertyConditional pc in propertyConditionals)
{
if (pc.Matches(target)) { return true; }
}
}
return false;
case PropertyConditional.Comparison.And:
foreach (ISerializableEntity target in targets)
{
if (target == null || target.SerializableProperties == null) { continue; }
foreach (PropertyConditional pc in propertyConditionals)
{
if (!pc.Matches(target)) { return false; }
}
}
return true;
default:
throw new NotImplementedException();
}
}
protected bool IsValidTarget(ISerializableEntity entity)
{
if (entity is Item item)
{
if (item.HasTag(targetIdentifiers)) return true;
if (targetIdentifiers.Any(id => id == item.Prefab.Identifier)) return true;
}
else if (entity is ItemComponent itemComponent)
{
if (itemComponent.Item.HasTag(targetIdentifiers)) return true;
if (targetIdentifiers.Any(id => id == itemComponent.Item.Prefab.Identifier)) return true;
}
else if (entity is Structure structure)
{
if (targetIdentifiers.Any(id => id == structure.Prefab.Identifier)) return true;
}
else if (entity is Character character)
{
if (targetIdentifiers.Any(id => id == character.SpeciesName)) return true;
}
return targetIdentifiers.Any(id => id == entity.Name);
}
public void SetUser(Character user)
{
foreach (Affliction affliction in Afflictions)
{
affliction.Source = user;
}
return false;
}
protected bool IsValidTarget(ISerializableEntity entity)
@@ -498,7 +557,7 @@ namespace Barotrauma
if (duration > 0.0f && !Stackable)
{
//ignore if not stackable and there's already an identical statuseffect
DurationListElement existingEffect = DurationList.Find(d => d.Parent == this && d.Targets.Count == 1 && d.Targets[0] == target);
DurationListElement existingEffect = DurationList.Find(d => d.Parent == this && d.Targets.FirstOrDefault() == target);
if (existingEffect != null)
{
existingEffect.Timer = Math.Max(existingEffect.Timer, duration);
@@ -513,23 +572,30 @@ namespace Barotrauma
Apply(deltaTime, entity, targets);
}
public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
protected readonly List<ISerializableEntity> currentTargets = new List<ISerializableEntity>();
public virtual void Apply(ActionType type, float deltaTime, Entity entity, IEnumerable<ISerializableEntity> targets)
{
if (this.type != type) return;
//remove invalid targets
if (targetIdentifiers != null)
currentTargets.Clear();
foreach (ISerializableEntity target in targets)
{
targets.RemoveAll(t => !IsValidTarget(t));
if (targets.Count == 0) return;
if (targetIdentifiers != null)
{
//ignore invalid targets
if (!IsValidTarget(target)) { continue; }
}
currentTargets.Add(target);
}
if (!HasRequiredItems(entity) || !HasRequiredConditions(targets)) return;
if (targetIdentifiers != null && currentTargets.Count == 0) { return; }
if (!HasRequiredItems(entity) || !HasRequiredConditions(currentTargets)) return;
if (duration > 0.0f && !Stackable)
{
//ignore if not stackable and there's already an identical statuseffect
DurationListElement existingEffect = DurationList.Find(d => d.Parent == this && d.Targets.SequenceEqual(targets));
DurationListElement existingEffect = DurationList.Find(d => d.Parent == this && d.Targets.SequenceEqual(currentTargets));
if (existingEffect != null)
{
existingEffect.Timer = Math.Max(existingEffect.Timer, duration);
@@ -537,7 +603,7 @@ namespace Barotrauma
}
}
Apply(deltaTime, entity, targets);
Apply(deltaTime, entity, currentTargets);
}
protected void Apply(float deltaTime, Entity entity, List<ISerializableEntity> targets)
@@ -609,7 +675,7 @@ namespace Barotrauma
if (removeItem)
{
foreach (Item item in targets.FindAll(t => t is Item).Cast<Item>())
foreach (Item item in targets.Where(t => t is Item).Cast<Item>())
{
Entity.Spawner?.AddToRemoveQueue(item);
}
@@ -640,7 +706,7 @@ namespace Barotrauma
{
if (target == null || target.SerializableProperties == null ||
!target.SerializableProperties.TryGetValue(propertyNames[i], out SerializableProperty property)) continue;
ApplyToProperty(property, propertyEffects[i], deltaTime);
ApplyToProperty(target, property, propertyEffects[i], deltaTime);
}
}
}
@@ -657,11 +723,11 @@ namespace Barotrauma
if (target is Character character)
{
character.LastDamageSource = entity;
character.CharacterHealth.ApplyAffliction(null, multipliedAffliction);
character.AddDamage(entity.WorldPosition, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false);
}
else if (target is Limb limb)
{
limb.character.CharacterHealth.ApplyAffliction(limb, multipliedAffliction);
limb.character.DamageLimb(entity.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
}
}
@@ -684,6 +750,67 @@ namespace Barotrauma
var fire = new FireSource(entity.WorldPosition, hull);
fire.Size = new Vector2(FireSize, fire.Size.Y);
}
bool isNotClient = true;
#if CLIENT
isNotClient = GameMain.Client == null;
#endif
if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
{
foreach (ItemSpawnInfo itemSpawnInfo in spawnItems)
{
switch (itemSpawnInfo.SpawnPosition)
{
case ItemSpawnInfo.SpawnPositionType.This:
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, entity.WorldPosition);
break;
case ItemSpawnInfo.SpawnPositionType.ThisInventory:
{
if (entity is Character character)
{
if (character.Inventory != null && character.Inventory.Items.Any(it => it == null))
{
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, character.Inventory);
}
}
else if (entity is Item item)
{
var inventory = item?.GetComponent<ItemContainer>()?.Inventory;
if (inventory != null && inventory.Items.Any(it => it == null))
{
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
}
}
}
break;
case ItemSpawnInfo.SpawnPositionType.ContainedInventory:
{
Inventory thisInventory = null;
if (entity is Character character)
{
thisInventory = character.Inventory;
}
else if (entity is Item item)
{
thisInventory = item?.GetComponent<ItemContainer>()?.Inventory;
}
if (thisInventory != null)
{
foreach (Item item in thisInventory.Items)
{
if (item == null) continue;
Inventory containedInventory = item.GetComponent<ItemContainer>()?.Inventory;
if (containedInventory == null || !containedInventory.Items.Any(i => i == null)) continue;
Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, containedInventory);
break;
}
}
}
break;
}
}
}
if (GameMain.Client == null && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
{
@@ -761,36 +888,36 @@ namespace Barotrauma
#endif
}
private void ApplyToProperty(SerializableProperty property, object value, float deltaTime)
private void ApplyToProperty(ISerializableEntity target, SerializableProperty property, object value, float deltaTime)
{
if (disableDeltaTime || setValue) deltaTime = 1.0f;
Type type = value.GetType();
if (type == typeof(float) ||
(type == typeof(int) && property.GetValue() is float))
(type == typeof(int) && property.GetValue(target) is float))
{
float floatValue = Convert.ToSingle(value) * deltaTime;
if (!setValue) floatValue += (float)property.GetValue();
property.TrySetValue(floatValue);
if (!setValue) floatValue += (float)property.GetValue(target);
property.TrySetValue(target, floatValue);
}
else if (type == typeof(int) && value is int)
{
int intValue = (int)((int)value * deltaTime);
if (!setValue) intValue += (int)property.GetValue();
property.TrySetValue(intValue);
if (!setValue) intValue += (int)property.GetValue(target);
property.TrySetValue(target, intValue);
}
else if (type == typeof(bool) && value is bool)
{
property.TrySetValue((bool)value);
property.TrySetValue(target, (bool)value);
}
else if (type == typeof(string))
{
property.TrySetValue((string)value);
property.TrySetValue(target, (string)value);
}
else
{
DebugConsole.ThrowError("Couldn't apply value " + value.ToString() + " (" + type + ") to property \"" + property.Name + "\" (" + property.GetValue().GetType() + ")! "
DebugConsole.ThrowError("Couldn't apply value " + value.ToString() + " (" + type + ") to property \"" + property.Name + "\" (" + property.GetValue(target).GetType() + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
}
@@ -821,8 +948,40 @@ namespace Barotrauma
{
for (int n = 0; n < element.Parent.propertyNames.Length; n++)
{
if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(element.Parent.propertyNames[n], out SerializableProperty property)) continue;
element.Parent.ApplyToProperty(property, element.Parent.propertyEffects[n], CoroutineManager.UnscaledDeltaTime);
if (target == null ||
target.SerializableProperties == null ||
!target.SerializableProperties.TryGetValue(element.Parent.propertyNames[n], out SerializableProperty property))
{
continue;
}
element.Parent.ApplyToProperty(target, property, element.Parent.propertyEffects[n], CoroutineManager.UnscaledDeltaTime);
}
foreach (Affliction affliction in element.Parent.Afflictions)
{
Affliction multipliedAffliction = affliction;
if (!element.Parent.disableDeltaTime) { multipliedAffliction = affliction.CreateMultiplied(deltaTime); }
if (target is Character character)
{
character.AddDamage(character.WorldPosition, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false);
}
else if (target is Limb limb)
{
limb.character.DamageLimb(limb.WorldPosition, limb, new List<Affliction>() { multipliedAffliction }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
}
}
foreach (Pair<string, float> reduceAffliction in element.Parent.ReduceAffliction)
{
if (target is Character)
{
((Character)target).CharacterHealth.ReduceAffliction(null, reduceAffliction.First, reduceAffliction.Second * deltaTime);
}
else if (target is Limb limb)
{
limb.character.CharacterHealth.ReduceAffliction(limb, reduceAffliction.First, reduceAffliction.Second * deltaTime);
}
}
foreach (Affliction affliction in element.Parent.Afflictions)