Client LuaCsForBarotrauma
CharacterAbility.cs
1 using System;
2 using System.Reflection;
3 
4 namespace Barotrauma.Abilities
5 {
6  abstract class CharacterAbility
7  {
10  public Character Character { get; }
11 
12  public bool RequiresAlive { get; }
13 
14  public virtual bool AllowClientSimulation => false;
15  public virtual bool AppliesEffectOnIntervalUpdate => false;
16 
17  private const float DefaultEffectTime = 1.0f;
18 
19  // currently resets if the character dies. would need to be stored in a dictionary of sorts to maintain through death
20 
21 
25  protected float EffectDeltaTime => CharacterAbilityGroup is CharacterAbilityGroupInterval abilityGroupInterval ? abilityGroupInterval.TimeSinceLastUpdate : DefaultEffectTime;
26 
27  public CharacterAbility(CharacterAbilityGroup characterAbilityGroup, ContentXElement abilityElement)
28  {
29  CharacterAbilityGroup = characterAbilityGroup ?? throw new ArgumentNullException(nameof(characterAbilityGroup));
30  CharacterTalent = characterAbilityGroup.CharacterTalent;
32  RequiresAlive = abilityElement.GetAttributeBool("requiresalive", true);
33  }
34 
35  public bool IsViable()
36  {
37  if (!AllowClientSimulation && GameMain.NetworkMember is { IsClient: true }) { return false; }
38  if (RequiresAlive && Character.IsDead) { return false; }
39  return true;
40  }
41 
42  public virtual void InitializeAbility(bool addingFirstTime) { }
43 
44  public virtual void UpdateCharacterAbility(bool conditionsMatched, float timeSinceLastUpdate)
45  {
46  // may need a separate Update for changing state on non-interval-based abilities
48  {
49  if (conditionsMatched)
50  {
51  ApplyEffect();
52  }
53  }
54  else
55  {
56  VerifyState(conditionsMatched, timeSinceLastUpdate);
57  }
58  }
59 
60  protected virtual void VerifyState(bool conditionsMatched, float timeSinceLastUpdate)
61  {
62  DebugConsole.ThrowError($"Error in talent {CharacterTalent.DebugIdentifier}: Ability {this} does not have an implementation for VerifyState! This ability does not work in interval ability groups.",
63  contentPackage: CharacterTalent.Prefab.ContentPackage);
64  }
65 
66  public void ApplyAbilityEffect(AbilityObject abilityObject)
67  {
68  if (abilityObject is null)
69  {
70  ApplyEffect();
71  }
72  else
73  {
74  ApplyEffect(abilityObject);
75  }
76  }
77 
78  protected virtual void ApplyEffect()
79  {
80  DebugConsole.AddWarning($"Ability {this} used improperly! This ability does not have a definition for ApplyEffect in talent {CharacterTalent.DebugIdentifier}",
82  }
83 
84  protected virtual void ApplyEffect(AbilityObject abilityObject)
85  {
86  DebugConsole.AddWarning($"Ability {this} used improperly! This ability does not take a parameter for ApplyEffect in talent {CharacterTalent.DebugIdentifier}",
88  }
89 
90  protected void LogAbilityObjectMismatch()
91  {
92  DebugConsole.ThrowError($"Incompatible ability! Ability {this} is incompatitible with this type of ability effect type in talent {CharacterTalent.DebugIdentifier}",
93  contentPackage: CharacterTalent.Prefab.ContentPackage);
94  }
95 
96  // XML
97  public static CharacterAbility Load(ContentXElement abilityElement, CharacterAbilityGroup characterAbilityGroup, bool errorMessages = true)
98  {
99  Type abilityType;
100  string type = abilityElement.Name.ToString().ToLowerInvariant();
101  try
102  {
103  abilityType = ReflectionUtils.GetTypeWithBackwardsCompatibility("Barotrauma.Abilities", type, false, true);
104  if (abilityType == null)
105  {
106  if (errorMessages) DebugConsole.ThrowError("Could not find the CharacterAbility \"" + type + "\" (" + characterAbilityGroup.CharacterTalent.DebugIdentifier + ")",
107  contentPackage: abilityElement.ContentPackage);
108  return null;
109  }
110  }
111  catch (Exception e)
112  {
113  if (errorMessages)
114  {
115  DebugConsole.ThrowError("Could not find the CharacterAbility \"" + type + "\" (" + characterAbilityGroup.CharacterTalent.DebugIdentifier + ")", e,
116  contentPackage: abilityElement.ContentPackage);
117  }
118  return null;
119  }
120 
121  object[] args = { characterAbilityGroup, abilityElement };
122  CharacterAbility characterAbility;
123 
124  try
125  {
126  characterAbility = (CharacterAbility)Activator.CreateInstance(abilityType, args);
127  }
128  catch (TargetInvocationException e)
129  {
130  DebugConsole.ThrowError("Error while creating an instance of a CharacterAbility of the type " + abilityType + ".", e.InnerException,
131  contentPackage: abilityElement.ContentPackage);
132  return null;
133  }
134 
135  return characterAbility;
136  }
137  }
138 }
float EffectDeltaTime
Used primarily for StatusEffects. Default to constant outside interval abilities.
virtual void UpdateCharacterAbility(bool conditionsMatched, float timeSinceLastUpdate)
virtual void VerifyState(bool conditionsMatched, float timeSinceLastUpdate)
void ApplyAbilityEffect(AbilityObject abilityObject)
virtual void InitializeAbility(bool addingFirstTime)
CharacterAbility(CharacterAbilityGroup characterAbilityGroup, ContentXElement abilityElement)
static CharacterAbility Load(ContentXElement abilityElement, CharacterAbilityGroup characterAbilityGroup, bool errorMessages=true)
virtual void ApplyEffect(AbilityObject abilityObject)
readonly TalentPrefab Prefab
ContentPackage? ContentPackage
bool GetAttributeBool(string key, bool def)
static NetworkMember NetworkMember
Definition: GameMain.cs:190
ContentPackage? ContentPackage
Definition: Prefab.cs:37