Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/Source/Characters/StatusEffect.cs
Alex Noir a2a4225598 Added a fully functional syringe gun! Accepts syringes as ammo. Has custom sprite and sound.
Made syringes have a "projectile" component for syringe guns
Adds several missing signal components to the fabricator, as well as medical syringe to medical fabricator
Adds support for status effects applied to characters from onImpact
Removed "contained.Condition = 0.0f;" in Projectile.cs due to it limiting the possibilities of the .xml content creation
Added a couple null checks in StatusEffect.cs due to crashes caused by the new projectile changes - might need to debug further, perhaps there's a root cause?
Added itemlist console command
2017-12-10 22:17:14 +03:00

374 lines
12 KiB
C#

using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
#if CLIENT
using Barotrauma.Particles;
#endif
namespace Barotrauma
{
partial class StatusEffect
{
[Flags]
public enum TargetType
{
This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16, UseTarget = 32, Hull = 64
}
private TargetType targetTypes;
private HashSet<string> targetNames;
private List<RelatedItem> requiredItems;
#if CLIENT
private List<ParticleEmitter> particleEmitters;
private Sound sound;
private bool loopSound;
#endif
public string[] propertyNames;
private object[] propertyEffects;
private bool setValue;
private bool disableDeltaTime;
private HashSet<string> onContainingNames;
private readonly float duration;
private readonly bool useItem;
public readonly ActionType type;
private Explosion explosion;
public readonly float FireSize;
public TargetType Targets
{
get { return targetTypes; }
}
public HashSet<string> TargetNames
{
get { return targetNames; }
}
public HashSet<string> OnContainingNames
{
get { return onContainingNames; }
}
public static StatusEffect Load(XElement element)
{
if (element.Attribute("delay")!=null)
{
return new DelayedEffect(element);
}
return new StatusEffect(element);
}
protected StatusEffect(XElement element)
{
requiredItems = new List<RelatedItem>();
#if CLIENT
particleEmitters = new List<ParticleEmitter>();
#endif
IEnumerable<XAttribute> attributes = element.Attributes();
List<XAttribute> propertyAttributes = new List<XAttribute>();
foreach (XAttribute attribute in attributes)
{
switch (attribute.Name.ToString())
{
case "type":
try
{
type = (ActionType)Enum.Parse(typeof(ActionType), attribute.Value, true);
}
catch
{
string[] split = attribute.Value.Split('=');
type = (ActionType)Enum.Parse(typeof(ActionType), split[0], true);
string[] containingNames = split[1].Split(',');
onContainingNames = new HashSet<string>();
for (int i = 0; i < containingNames.Length; i++)
{
onContainingNames.Add(containingNames[i].Trim());
}
}
break;
case "target":
string[] Flags = attribute.Value.Split(',');
foreach (string s in Flags)
{
targetTypes |= (TargetType)Enum.Parse(typeof(TargetType), s, true);
}
break;
case "disabledeltatime":
disableDeltaTime = attribute.GetAttributeBool(false);
break;
case "setvalue":
setValue = attribute.GetAttributeBool(false);
break;
case "targetnames":
string[] names = attribute.Value.Split(',');
targetNames = new HashSet<string>();
for (int i=0; i < names.Length; i++ )
{
targetNames.Add(names[i].Trim());
}
break;
case "duration":
duration = attribute.GetAttributeFloat(0.0f);
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.");
break;
default:
propertyAttributes.Add(attribute);
break;
}
}
int count = propertyAttributes.Count;
propertyNames = new string[count];
propertyEffects = new object[count];
int n = 0;
foreach (XAttribute attribute in propertyAttributes)
{
propertyNames[n] = attribute.Name.ToString().ToLowerInvariant();
propertyEffects[n] = XMLExtensions.GetAttributeObject(attribute);
n++;
}
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "explosion":
explosion = new Explosion(subElement);
break;
case "fire":
FireSize = subElement.GetAttributeFloat("size",10.0f);
break;
case "use":
case "useitem":
useItem = true;
break;
case "requireditem":
case "requireditems":
RelatedItem newRequiredItem = RelatedItem.Load(subElement);
if (newRequiredItem == null) continue;
requiredItems.Add(newRequiredItem);
break;
#if CLIENT
case "particleemitter":
particleEmitters.Add(new ParticleEmitter(subElement));
break;
case "sound":
sound = Sound.Load(subElement);
loopSound = subElement.GetAttributeBool("loop", false);
break;
#endif
}
}
}
private bool HasRequiredItems(Entity entity)
{
if (requiredItems == null) return true;
foreach (RelatedItem requiredItem in requiredItems)
{
Item item = entity as Item;
if (item != null)
{
if (!requiredItem.CheckRequirements(null, item)) return false;
}
Character character = entity as Character;
if (character != null)
{
if (!requiredItem.CheckRequirements(character, null)) return false;
}
}
return true;
}
public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target)
{
if (this.type != type || !HasRequiredItems(entity)) return;
if (targetNames != null && !targetNames.Contains(target.Name)) return;
List<ISerializableEntity> targets = new List<ISerializableEntity>();
targets.Add(target);
Apply(deltaTime, entity, targets);
}
public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
{
if (this.type != type || !HasRequiredItems(entity)) return;
Apply(deltaTime, entity, targets);
}
protected void Apply(float deltaTime, Entity entity, List<ISerializableEntity> targets)
{
#if CLIENT
if (sound != null)
{
if (loopSound)
{
if (!Sounds.SoundManager.IsPlaying(sound))
{
sound.Play(entity.WorldPosition);
}
else
{
sound.UpdatePosition(entity.WorldPosition);
}
}
else
{
sound.Play(entity.WorldPosition);
}
}
#endif
if (useItem)
{
foreach (Item item in targets.FindAll(t => t is Item).Cast<Item>())
{
item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character);
}
}
foreach (ISerializableEntity target in targets)
{
for (int i = 0; i < propertyNames.Length; i++)
{
SerializableProperty property;
if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue;
if (duration > 0.0f)
{
CoroutineManager.StartCoroutine(
ApplyToPropertyOverDuration(duration, property, propertyEffects[i]), "statuseffect");
}
else
{
ApplyToProperty(property, propertyEffects[i], deltaTime);
}
}
}
if (explosion != null) explosion.Explode(entity.WorldPosition);
Hull hull = null;
if (entity is Character)
{
hull = ((Character)entity).AnimController.CurrentHull;
}
else if (entity is Item)
{
hull = ((Item)entity).CurrentHull;
}
if (FireSize > 0.0f)
{
var fire = new FireSource(entity.WorldPosition, hull);
fire.Size = new Vector2(FireSize, fire.Size.Y);
}
#if CLIENT
foreach (ParticleEmitter emitter in particleEmitters)
{
emitter.Emit(deltaTime, entity.WorldPosition, hull);
}
#endif
}
private IEnumerable<object> ApplyToPropertyOverDuration(float duration, SerializableProperty property, object value)
{
float timer = duration;
while (timer > 0.0f)
{
ApplyToProperty(property, value, CoroutineManager.UnscaledDeltaTime);
timer -= CoroutineManager.DeltaTime;
yield return CoroutineStatus.Running;
}
yield return CoroutineStatus.Success;
}
private void ApplyToProperty(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))
{
float floatValue = Convert.ToSingle(value) * deltaTime;
if (!setValue) floatValue += (float)property.GetValue();
property.TrySetValue(floatValue);
}
else if (type == typeof(int) && value is int)
{
int intValue = (int)((int)value * deltaTime);
if (!setValue) intValue += (int)property.GetValue();
property.TrySetValue(intValue);
}
else if (type == typeof(bool) && value is bool)
{
property.TrySetValue((bool)value);
}
else if (type == typeof(string))
{
property.TrySetValue((string)value);
}
else
{
DebugConsole.ThrowError("Couldn't apply value " + value.ToString() + " (" + type + ") to property \"" + property.Name + "\" (" + property.GetValue().GetType() + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
}
public static void UpdateAll(float deltaTime)
{
for (int i = DelayedEffect.List.Count-1; i>= 0; i--)
{
DelayedEffect.List[i].Update(deltaTime);
}
}
public static void StopAll()
{
CoroutineManager.StopCoroutines("statuseffect");
}
}
}