Server LuaCsForBarotrauma
Wearable.cs
1 using Microsoft.Xna.Framework;
2 using System;
3 using System.Collections.Generic;
4 using Barotrauma.IO;
5 using System.Linq;
6 using System.Xml.Linq;
10 using System.Collections.Immutable;
11 
12 namespace Barotrauma
13 {
14  public enum WearableType
15  {
16  Item,
17  Hair,
18  Beard,
19  Moustache,
21  Husk,
22  Herpes
23  }
24 
26  {
27  public ContentPath UnassignedSpritePath { get; private set; }
28  public string SpritePath { get; private set; }
29  public ContentXElement SourceElement { get; private set; }
30 
31  public WearableType Type { get; private set; }
32  private Sprite _sprite;
33  public Sprite Sprite
34  {
35  get { return _sprite; }
36  private set
37  {
38  if (value == _sprite) { return; }
39  if (_sprite != null)
40  {
41  _sprite.Remove();
42  }
43  _sprite = value;
44  }
45  }
46  public LimbType Limb { get; private set; }
47  public bool HideLimb { get; private set; }
48 
49  public enum ObscuringMode
50  {
51  None,
52  Hide,
53  AlphaClip
54  }
55  public ObscuringMode ObscureOtherWearables { get; private set; }
58  public bool CanBeHiddenByOtherWearables { get; private set; }
59 
63  public ImmutableHashSet<Identifier> CanBeHiddenByItem { get; private set; }
64  public List<WearableType> HideWearablesOfType { get; private set; }
65  public bool InheritLimbDepth { get; private set; }
69  public bool InheritScale { get; private set; }
70  public bool IgnoreRagdollScale { get; private set; }
71  public bool IgnoreLimbScale { get; private set; }
72  public bool IgnoreTextureScale { get; private set; }
73  public bool InheritOrigin { get; private set; }
74  public bool InheritSourceRect { get; private set; }
75 
76  public float Scale { get; private set; }
77 
78  public float Rotation { get; private set; }
79 
80  public LimbType DepthLimb { get; private set; }
81  private Wearable _wearableComponent;
83  {
84  get { return _wearableComponent; }
85  set
86  {
87  if (value == _wearableComponent) { return; }
88  if (_wearableComponent != null)
89  {
90  _wearableComponent.Remove();
91  }
92  _wearableComponent = value;
93  }
94  }
95  public string Sound { get; private set; }
96  public Point? SheetIndex { get; private set; }
97 
98  public LightComponent LightComponent => LightComponents?.FirstOrDefault();
99 
100  public List<LightComponent> LightComponents
101  {
102  get
103  {
104  if (_lightComponents == null)
105  {
106  _lightComponents = new List<LightComponent>();
107  }
108  return _lightComponents;
109  }
110  }
111  private List<LightComponent> _lightComponents;
112 
113  public int Variant { get; set; }
114 
115  private Character _picker;
121  {
122  get { return _picker; }
123  set
124  {
125  if (value == _picker) { return; }
126  _picker = value;
127  IsInitialized = false;
128  UnassignedSpritePath = ParseSpritePath(SourceElement);
129  Init(_picker);
130  }
131  }
132 
133  public WearableSprite(ContentXElement subElement, WearableType type)
134  {
135  Type = type;
136  SourceElement = subElement;
138  Init();
139  switch (type)
140  {
141  case WearableType.Hair:
142  case WearableType.Beard:
143  case WearableType.Moustache:
144  case WearableType.FaceAttachment:
145  case WearableType.Husk:
146  case WearableType.Herpes:
147  Limb = LimbType.Head;
148  break;
149  }
150  }
151 
155  public WearableSprite(ContentXElement subElement, Wearable wearable, int variant = 0)
156  {
157  Type = WearableType.Item;
158  WearableComponent = wearable;
159  Variant = Math.Max(variant, 0);
160  UnassignedSpritePath = ParseSpritePath(subElement);
161  SourceElement = subElement;
162  }
163 
164  private ContentPath ParseSpritePath(ContentXElement element)
165  {
166  if (element.DoesAttributeReferenceFileNameAlone("texture"))
167  {
168  string textureName = element.GetAttributeString("texture", "");
169  return ContentPath.FromRaw(
170  element.ContentPackage,
171  $"{Path.GetDirectoryName(WearableComponent.Item.Prefab.FilePath)}/{textureName}");
172  }
173  else
174  {
175  return element.GetAttributeContentPath("texture") ?? ContentPath.Empty;
176  }
177  }
178 
179  public void ParsePath(bool parseSpritePath)
180  {
181 #if SERVER
182  // Server doesn't care about texture paths at all
183  return;
184 #endif
186  if (_picker?.Info != null)
187  {
189  }
190  SpritePath = SpritePath.Replace("[VARIANT]", Variant.ToString());
191  if (!File.Exists(SpritePath))
192  {
193  // If the variant does not exist, parse the path so that it uses first variant.
194  SpritePath = SpritePath.Replace("[VARIANT]", "1");
195  }
196  if (!File.Exists(SpritePath) && _picker?.Info == null)
197  {
198  // If there's no character info is defined, try to use first tagset from CharacterInfoPrefab
199  var charInfoPrefab = CharacterPrefab.HumanPrefab.CharacterInfoPrefab;
200  SpritePath = charInfoPrefab.ReplaceVars(SpritePath, charInfoPrefab.Heads.First());
201  }
202  if (parseSpritePath)
203  {
205  }
206  }
207 
208  public bool IsInitialized { get; private set; }
209  public void Init(Character picker = null)
210  {
211  if (IsInitialized) { return; }
212 
213  _picker = picker;
214  ParsePath(false);
215  Sprite?.Remove();
216  Sprite = new Sprite(SourceElement, file: SpritePath);
217  Limb = (LimbType)Enum.Parse(typeof(LimbType), SourceElement.GetAttributeString("limb", "Head"), true);
218  HideLimb = SourceElement.GetAttributeBool("hidelimb", false);
219 
220  foreach (var mode in Enum.GetValues<ObscuringMode>())
221  {
222  if (mode == ObscuringMode.None) { continue; }
223  if (SourceElement.GetAttributeBool($"{mode}OtherWearables", false))
224  {
225  ObscureOtherWearables = mode;
226  }
227  }
228 
229  CanBeHiddenByOtherWearables = SourceElement.GetAttributeBool("canbehiddenbyotherwearables", true);
230  CanBeHiddenByItem = SourceElement.GetAttributeIdentifierArray(nameof(CanBeHiddenByItem), Array.Empty<Identifier>()).ToImmutableHashSet();
231  InheritLimbDepth = SourceElement.GetAttributeBool("inheritlimbdepth", true);
232  var scale = SourceElement.GetAttribute("inheritscale");
233  if (scale != null)
234  {
235  InheritScale = scale.GetAttributeBool(Type != WearableType.Item);
236  }
237  else
238  {
239  InheritScale = SourceElement.GetAttributeBool("inherittexturescale", Type != WearableType.Item);
240  }
241  IgnoreLimbScale = SourceElement.GetAttributeBool("ignorelimbscale", false);
242  IgnoreTextureScale = SourceElement.GetAttributeBool("ignoretexturescale", false);
243  IgnoreRagdollScale = SourceElement.GetAttributeBool("ignoreragdollscale", false);
244  SourceElement.GetAttributeBool("inherittexturescale", false);
245  InheritOrigin = SourceElement.GetAttributeBool("inheritorigin", Type != WearableType.Item);
246  InheritSourceRect = SourceElement.GetAttributeBool("inheritsourcerect", Type != WearableType.Item);
247  DepthLimb = (LimbType)Enum.Parse(typeof(LimbType), SourceElement.GetAttributeString("depthlimb", "None"), true);
248  Sound = SourceElement.GetAttributeString("sound", "");
249  Scale = SourceElement.GetAttributeFloat("scale", 1.0f);
250  Rotation = MathHelper.ToRadians(SourceElement.GetAttributeFloat("rotation", 0.0f));
251  var index = SourceElement.GetAttributePoint("sheetindex", new Point(-1, -1));
252  if (index.X > -1 && index.Y > -1)
253  {
254  SheetIndex = index;
255  }
256 
257  HideWearablesOfType = new List<WearableType>();
258  var wearableTypes = SourceElement.GetAttributeStringArray("hidewearablesoftype", null);
259  if (wearableTypes != null && wearableTypes.Length > 0)
260  {
261  foreach (var value in wearableTypes)
262  {
263  if (Enum.TryParse(value, ignoreCase: true, out WearableType wearableType))
264  {
265  HideWearablesOfType.Add(wearableType);
266  }
267  }
268  }
269 
270  IsInitialized = true;
271  }
272 
273  public void Remove()
274  {
275  Sprite?.Remove();
276  //don't use the Picker setter, because it causes the sprite to be re-initialized for "no character"
277  _picker = null;
278  }
279  }
280 }
281 
283 {
285  {
286  private readonly ContentXElement[] wearableElements;
287  private readonly WearableSprite[] wearableSprites;
288  private readonly LimbType[] limbType;
289  private readonly Limb[] limb;
290 
291  private readonly List<DamageModifier> damageModifiers;
292  public readonly Dictionary<Identifier, float> SkillModifiers;
293 
294  public readonly Dictionary<StatTypes, float> WearableStatValues = new Dictionary<StatTypes, float>();
295 
296  public IEnumerable<DamageModifier> DamageModifiers
297  {
298  get { return damageModifiers; }
299  }
300 
301  public bool AutoEquipWhenFull { get; private set; }
302  public bool DisplayContainedStatus { get; private set; }
303 
304  [Serialize(false, IsPropertySaveable.No, description: "Can the item be used (assuming it has components that are usable in some way) when worn.")]
305  public bool AllowUseWhenWorn { get; set; }
306 
307  public readonly int Variants;
308 
309  private int variant;
310  public int Variant
311  {
312  get { return variant; }
313  set
314  {
315  if (variant == value) { return; }
316 #if SERVER
317  variant = value;
318  if (!item.Submarine?.Loading ?? true)
319  {
320  item.CreateServerEvent(this);
321  }
322 #elif CLIENT
323 
324  Character character = picker;
325  if (character != null)
326  {
327  Unequip(character);
328  }
329 
330  for (int i = 0; i < wearableSprites.Length; i++)
331  {
332  var subElement = wearableElements[i];
333 
334  wearableSprites[i]?.Sprite?.Remove();
335  wearableSprites[i] = new WearableSprite(subElement, this, value);
336  }
337 
338  if (character != null)
339  {
340  Equip(character);
341  }
342 
343  variant = value;
344 #endif
345  }
346  }
347 
351  public readonly float PressureProtection;
352 
353  public Wearable(Item item, ContentXElement element) : base(item, element)
354  {
355  this.item = item;
356 
357  damageModifiers = new List<DamageModifier>();
358  SkillModifiers = new Dictionary<Identifier, float>();
359 
360  int spriteCount = element.Elements().Count(x => x.Name.ToString().ToLowerInvariant() == "sprite");
361  Variants = element.GetAttributeInt("variants", 0);
362  variant = Rand.Range(1, Variants + 1, Rand.RandSync.ServerAndClient);
363  wearableSprites = new WearableSprite[spriteCount];
364  wearableElements = new ContentXElement[spriteCount];
365  limbType = new LimbType[spriteCount];
366  limb = new Limb[spriteCount];
367  AutoEquipWhenFull = element.GetAttributeBool("autoequipwhenfull", true);
368  DisplayContainedStatus = element.GetAttributeBool("displaycontainedstatus", false);
369  int i = 0;
370  foreach (var subElement in element.Elements())
371  {
372  switch (subElement.Name.ToString().ToLowerInvariant())
373  {
374  case "sprite":
375  if (subElement.GetAttribute("texture") == null)
376  {
377  DebugConsole.ThrowError("Item \"" + item.Name + "\" doesn't have a texture specified!",
378  contentPackage: element.ContentPackage);
379  return;
380  }
381 
382  limbType[i] = (LimbType)Enum.Parse(typeof(LimbType),
383  subElement.GetAttributeString("limb", "Head"), true);
384 
385  wearableSprites[i] = new WearableSprite(subElement, this, variant);
386  wearableElements[i] = subElement;
387 
388  foreach (var lightElement in subElement.Elements())
389  {
390  if (!lightElement.Name.ToString().Equals("lightcomponent", StringComparison.OrdinalIgnoreCase)) { continue; }
391  wearableSprites[i].LightComponents.Add(new LightComponent(item, lightElement)
392  {
393  Parent = this
394  });
395  foreach (var light in wearableSprites[i].LightComponents)
396  {
397  item.AddComponent(light);
398  }
399  }
400 
401  i++;
402  break;
403  case "damagemodifier":
404  damageModifiers.Add(new DamageModifier(subElement, item.Name + ", Wearable"));
405  break;
406  case "skillmodifier":
407  Identifier skillIdentifier = subElement.GetAttributeIdentifier("skillidentifier", Identifier.Empty);
408  float skillValue = subElement.GetAttributeFloat("skillvalue", 0f);
409  if (SkillModifiers.ContainsKey(skillIdentifier))
410  {
411  SkillModifiers[skillIdentifier] += skillValue;
412  }
413  else
414  {
415  SkillModifiers.TryAdd(skillIdentifier, skillValue);
416  }
417  break;
418  case "statvalue":
419  StatTypes statType = CharacterAbilityGroup.ParseStatType(subElement.GetAttributeString("stattype", ""), Name);
420  float statValue = subElement.GetAttributeFloat("value", 0f);
421  if (WearableStatValues.ContainsKey(statType))
422  {
423  WearableStatValues[statType] += statValue;
424  }
425  else
426  {
427  WearableStatValues.TryAdd(statType, statValue);
428  }
429  break;
430  case "statuseffect":
431  if (subElement.GetAttributeString("Target", string.Empty).ToLowerInvariant().Contains("character"))
432  {
433  PressureProtection = Math.Max(subElement.GetAttributeFloat(nameof(PressureProtection), 0), PressureProtection);
434  }
435  break;
436  }
437  }
438  }
439 
440  public override void Equip(Character character)
441  {
442  foreach (var allowedSlot in allowedSlots)
443  {
444  if (allowedSlot == InvSlotType.Any) { continue; }
445  foreach (Enum value in Enum.GetValues(typeof(InvSlotType)))
446  {
447  var slotType = (InvSlotType)value;
448  if (slotType == InvSlotType.Any || slotType == InvSlotType.None) { continue; }
449  if (allowedSlot.HasFlag(slotType) && !character.Inventory.IsInLimbSlot(item, slotType))
450  {
451  return;
452  }
453  }
454  }
455 
456  picker = character;
457 
458  for (int i = 0; i < wearableSprites.Length; i++ )
459  {
460  var wearableSprite = wearableSprites[i];
461  if (!wearableSprite.IsInitialized) { wearableSprite.Init(picker); }
462  // If the item is gender specific (it has a different textures for male and female), we have to change the gender here so that the texture is updated.
463  wearableSprite.Picker = picker;
464 
465  Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
466  if (equipLimb == null) { continue; }
467 
468  if (item.body != null)
469  {
470  item.body.Enabled = false;
471  }
472  IsActive = true;
473  if (wearableSprite.LightComponent != null)
474  {
475  foreach (var light in wearableSprite.LightComponents)
476  {
477  light.ParentBody = equipLimb.body;
478  }
479  }
480 
481  limb[i] = equipLimb;
482  if (!equipLimb.WearingItems.Contains(wearableSprite))
483  {
484  equipLimb.WearingItems.Add(wearableSprite);
485  equipLimb.WearingItems.Sort((wearable, nextWearable) =>
486  {
487  float depth = wearable?.Sprite?.Depth ?? 0;
488  float nextDepth = nextWearable?.Sprite?.Depth ?? 0;
489  return nextDepth.CompareTo(depth);
490  });
491  equipLimb.WearingItems.Sort((wearable, nextWearable) =>
492  {
493  var wearableComponent = wearable?.WearableComponent;
494  var nextWearableComponent = nextWearable?.WearableComponent;
495  if (wearableComponent == null && nextWearableComponent == null) { return 0; }
496  if (wearableComponent == null) { return -1; }
497  if (nextWearableComponent == null) { return 1; }
498  return wearableComponent.AllowedSlots.Contains(InvSlotType.OuterClothes).CompareTo(nextWearableComponent.AllowedSlots.Contains(InvSlotType.OuterClothes));
499  });
500  }
501 #if CLIENT
502  equipLimb.UpdateWearableTypesToHide();
503 #endif
504  }
505  character.OnWearablesChanged();
506  }
507 
508  public override void Drop(Character dropper, bool setTransform = true)
509  {
510  Character previousPicker = picker;
511  Unequip(picker);
512  base.Drop(dropper, setTransform);
513  previousPicker?.OnWearablesChanged();
514  picker = null;
515  IsActive = false;
516  }
517 
518  public override void Unequip(Character character)
519  {
520  if (character == null || character.Removed) { return; }
521  if (picker == null) { return; }
522 
523  for (int i = 0; i < wearableSprites.Length; i++)
524  {
525  Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
526  if (equipLimb == null) { continue; }
527 
528  if (wearableSprites[i].LightComponent != null)
529  {
530  foreach (var light in wearableSprites[i].LightComponents)
531  {
532  light.ParentBody = null;
533  }
534  }
535 
536  equipLimb.WearingItems.RemoveAll(w => w != null && w == wearableSprites[i]);
537 #if CLIENT
538  equipLimb.UpdateWearableTypesToHide();
539 #endif
540  limb[i] = null;
541  }
542 
543  IsActive = false;
544  }
545 
546  public override void UpdateBroken(float deltaTime, Camera cam)
547  {
548  Update(deltaTime, cam);
549  }
550 
551  public override void Update(float deltaTime, Camera cam)
552  {
553  if (picker == null || picker.Removed)
554  {
555  IsActive = false;
556  return;
557  }
558 
559  //if the item is also being held, let the Holdable component control the position
560  if (item.GetComponent<Holdable>() is not { IsActive: true })
561  {
563  }
564  item.ApplyStatusEffects(ActionType.OnWearing, deltaTime, picker);
565 
566 #if CLIENT
567  PlaySound(ActionType.OnWearing, picker);
568 #endif
569  }
570 
571  protected override void RemoveComponentSpecific()
572  {
573  base.RemoveComponentSpecific();
574 
575  Unequip(picker);
576 
577  foreach (WearableSprite wearableSprite in wearableSprites)
578  {
579  wearableSprite.Remove();
580  }
581  }
582 
583  public override XElement Save(XElement parentElement)
584  {
585  XElement componentElement = base.Save(parentElement);
586  componentElement.Add(new XAttribute("variant", variant));
587  return componentElement;
588  }
589 
590  private int loadedVariant = -1;
591  public override void Load(ContentXElement componentElement, bool usePrefabValues, IdRemap idRemap, bool isItemSwap)
592  {
593  base.Load(componentElement, usePrefabValues, idRemap, isItemSwap);
594  loadedVariant = componentElement.GetAttributeInt("variant", -1);
595  }
596  public override void OnItemLoaded()
597  {
598  base.OnItemLoaded();
599  //do this here to prevent creating a network event before the item has been fully initialized
600  if (loadedVariant > 0 && loadedVariant < Variants + 1)
601  {
602  Variant = loadedVariant;
603  }
604  }
605  public override void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
606  {
607  msg.WriteByte((byte)Variant);
608  base.ServerEventWrite(msg, c, extraData);
609  }
610 
611  public override void ClientEventRead(IReadMessage msg, float sendingTime)
612  {
613  Variant = (int)msg.ReadByte();
614  base.ClientEventRead(msg, sendingTime);
615  }
616 
617  }
618 }
static StatTypes ParseStatType(string statTypeString, string debugIdentifier)
CharacterInfoPrefab CharacterInfoPrefab
static CharacterPrefab HumanPrefab
static ContentPath FromRaw(string? rawValue)
static readonly ContentPath Empty
Definition: ContentPath.cs:12
string??????????? Value
Definition: ContentPath.cs:27
string? GetAttributeString(string key, string? def)
Identifier[] GetAttributeIdentifierArray(Identifier[] def, params string[] keys)
Point GetAttributePoint(string key, in Point def)
float GetAttributeFloat(string key, float def)
ContentPackage? ContentPackage
IEnumerable< ContentXElement > Elements()
bool DoesAttributeReferenceFileNameAlone(string key)
ContentPath? GetAttributeContentPath(string key)
bool GetAttributeBool(string key, bool def)
int GetAttributeInt(string key, int def)
string?[] GetAttributeStringArray(string key, string[]? def, bool convertToLowerInvariant=false)
XAttribute? GetAttribute(string name)
Submarine Submarine
Definition: Entity.cs:53
void ApplyStatusEffects(ActionType type, float deltaTime, Character character=null, Limb limb=null, Entity useTarget=null, bool isNetworkEvent=false, Vector2? worldPosition=null)
Executes all StatusEffects of the specified type. Note that condition checks are ignored here: that s...
void SetTransform(Vector2 simPosition, float rotation, bool findNewHull=true, bool setPrevTransform=true)
void AddComponent(ItemComponent component)
override string Name
Note that this is not a LocalizedString instance, just the current name of the item as a string....
List< InvSlotType > allowedSlots
Definition: Pickable.cs:14
override XElement Save(XElement parentElement)
Definition: Wearable.cs:583
override void Equip(Character character)
Definition: Wearable.cs:440
override void ClientEventRead(IReadMessage msg, float sendingTime)
Definition: Wearable.cs:611
readonly Dictionary< StatTypes, float > WearableStatValues
Definition: Wearable.cs:294
override void OnItemLoaded()
Called when all the components of the item have been loaded. Use to initialize connections between co...
Definition: Wearable.cs:596
Wearable(Item item, ContentXElement element)
Definition: Wearable.cs:353
override void RemoveComponentSpecific()
Definition: Wearable.cs:571
override void Drop(Character dropper, bool setTransform=true)
a Character has dropped the item
Definition: Wearable.cs:508
IEnumerable< DamageModifier > DamageModifiers
Definition: Wearable.cs:297
override void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData=null)
Definition: Wearable.cs:605
readonly Dictionary< Identifier, float > SkillModifiers
Definition: Wearable.cs:292
readonly float PressureProtection
How deep down does the item protect from pressure? Determined by status effects.
Definition: Wearable.cs:351
override void Unequip(Character character)
Definition: Wearable.cs:518
override void Load(ContentXElement componentElement, bool usePrefabValues, IdRemap idRemap, bool isItemSwap)
Definition: Wearable.cs:591
override void Update(float deltaTime, Camera cam)
Definition: Wearable.cs:551
override void UpdateBroken(float deltaTime, Camera cam)
Definition: Wearable.cs:546
readonly List< WearableSprite > WearingItems
Definition: Limb.cs:529
PhysicsBody body
Definition: Limb.cs:217
Limb GetLimb(LimbType limbType, bool excludeSevered=true, bool excludeLimbsWithSecondaryType=false, bool useSecondaryType=false)
Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
Definition: Ragdoll.cs:2130
void Remove()
Definition: Sprite.cs:214
bool ParseTexturePath(string path="", string file="")
Definition: Sprite.cs:287
ImmutableHashSet< Identifier > CanBeHiddenByItem
Tags or identifiers of items that can hide this one.
Definition: Wearable.cs:63
void ParsePath(bool parseSpritePath)
Definition: Wearable.cs:179
ContentPath UnassignedSpritePath
Definition: Wearable.cs:27
bool InheritScale
Does the wearable inherit all the scalings of the wearer? Also the wearable's own scale is used!
Definition: Wearable.cs:69
ObscuringMode ObscureOtherWearables
Definition: Wearable.cs:55
List< LightComponent > LightComponents
Definition: Wearable.cs:101
Character Picker
None = Any/Not Defined -> no effect. Changing the gender forces re-initialization,...
Definition: Wearable.cs:121
WearableSprite(ContentXElement subElement, Wearable wearable, int variant=0)
Note: this constructor cannot initialize automatically, because the gender is unknown at this point....
Definition: Wearable.cs:155
List< WearableType > HideWearablesOfType
Definition: Wearable.cs:64
ContentXElement SourceElement
Definition: Wearable.cs:29
Wearable WearableComponent
Definition: Wearable.cs:83
WearableSprite(ContentXElement subElement, WearableType type)
Definition: Wearable.cs:133
void Init(Character picker=null)
Definition: Wearable.cs:209
Interface for entities that the server can send events to the clients
LimbType
Definition: Limb.cs:19
ActionType
ActionTypes define when a StatusEffect is executed.
Definition: Enums.cs:26
StatTypes
StatTypes are used to alter several traits of a character. They are mostly used by talents.
Definition: Enums.cs:195