1 using Microsoft.Xna.Framework;
3 using System.Collections.Generic;
8 using System.Collections.Immutable;
26 get => tags.ConvertToString();
27 set => tags = value.ToIdentifiers().ToHashSet();
29 private HashSet<Identifier> tags =
new HashSet<Identifier>();
31 public bool HasTag(Identifier tag) => tags.Contains(tag);
33 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"References to another species. Define only if the creature is a variant that needs to use a pre-existing translation."),
Editable]
36 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"Overrides the name of the character, shown to the player. If the display name is not defined, the game first tries to find the translated name. If that is not found, the species name will be used."),
Editable]
39 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"If defined, different species of the same group consider each other friendly and do not attack each other."),
Editable]
40 public Identifier
Group {
get;
private set; }
42 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"If enabled, the character is a humanoid and has different animation constraints relative to non-humanoid characters."),
Editable(ReadOnly =
true)]
45 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"If enabled, jobs can be assigned to characters of this species. Should be true for the player characters."),
Editable(ReadOnly =
true)]
54 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"If set true, this character only uses the climbing parameters defined in the walk parameters (not run)."),
Editable]
58 public bool Husk {
get;
private set; }
60 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"If this character can turn into a husk, which character it turns to? If not defined, uses the default pattern (e.g. Crawler -> Crawlerhusk, Human -> Humanhusk)."),
Editable]
63 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"If this character is a husk, from what species it can be turned into? If not defined, uses the default pattern (e.g. Crawlerhusk -> Crawler, Humanhusk -> Human)."),
Editable]
69 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Does this character need oxygen to survive? Enabling this also makes the character vulnerable to high pressure when swimming outside of the submarine."),
Editable]
75 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Note: non-humans with a human AI aren't fully supported. Enabling this on a non-human character may lead to issues.")]
78 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Is this creature an artificial creature, like robot or machine that shouldn't be affected by afflictions that affect only organic creatures? Overrides DoesBleed."),
Editable]
87 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Is this character's health shown at the top of the player's screen when they are in an active encounter?"),
Editable]
91 public float Noise {
get;
set; }
108 [
Serialize(
true,
IsPropertySaveable.Yes, description:
"Can the creature eat bodies? Used by player controlled creatures to allow them to eat. Currently applicable only to non-humanoids. To allow an AI controller to eat, just add an ai target with the state \"eat\""),
Editable]
111 [
Serialize(10f,
IsPropertySaveable.Yes, description:
"How effectively/easily the character eats other characters. Affects the forces, the amount of particles, and the time required before the target is eaten away"),
Editable(MinValueFloat = 1, MaxValueFloat = 1000, ValueStep = 1)]
117 [
Serialize(1f,
IsPropertySaveable.Yes,
"Decreases the intensive path finding call frequency. Set to a lower value for insignificant creatures to improve performance."),
Editable(minValue: 0f, maxValue: 1f)]
126 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"If set to a value greater than zero, this character creates disrupting noise on the sonar when within range."),
Editable]
129 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Range at which \"long distance\" blips for this character will appear on the sonar (used on some of the Abyss monsters)."),
Editable]
132 [
Serialize(25000f,
IsPropertySaveable.Yes,
"If the character is farther than this (in pixels) from the sub and the players, it will be disabled. The halved value is used for triggering simple physics where the ragdoll is disabled and only the main collider is updated."),
Editable(MinValueFloat = 10000f, MaxValueFloat = 100000f)]
138 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Should the character be drawn on top of characters that do not have this set? This currently has no effect if the character has no deformable sprites."),
Editable]
141 [
Serialize(1.0f,
IsPropertySaveable.Yes,
"Tells the bots how much they should prefer targeting this character with submarine weapons. Defaults to 1. Set 0 to tell the bots not to target this character at all. Distance to the target affects the decision making."),
Editable]
144 [
Serialize(1.0f,
IsPropertySaveable.Yes,
"Tells the bots how much they should prefer targeting this character with submarine weapons tagged as \"slowturret\", like railguns. The tag is arbitrary and can be added to any turrets, just like the priority. Defaults to 1. Not used if AITurretPriority is 0. Distance to the target affects the decision making."),
Editable]
154 public readonly List<SubParam>
SubParams =
new List<SubParam>();
155 public readonly List<SoundParams>
Sounds =
new List<SoundParams>();
156 public readonly List<ParticleParams>
BloodEmitters =
new List<ParticleParams>();
157 public readonly List<ParticleParams>
GibEmitters =
new List<ParticleParams>();
158 public readonly List<ParticleParams>
DamageEmitters =
new List<ParticleParams>();
159 public readonly List<InventoryParams>
Inventories =
new List<InventoryParams>();
175 protected override string GetName() =>
"Character Config File";
181 if (base.MainElement ==
null) {
return null; }
182 return base.MainElement.
IsOverride() ? base.MainElement.FirstElement() : base.MainElement;
188 XElement newXml = variantXML.CreateVariantXML(baseXML);
191 if (baseAi is
null || baseAi.Elements().None()
192 || variantAi is
null || variantAi.Elements().None())
198 var processedTags =
new HashSet<string>();
199 foreach (var aiTarget
in finalAiElement.Elements().ToArray())
201 string tag = aiTarget.GetAttributeString(
"tag",
null);
202 if (tag ==
null) {
continue; }
203 if (processedTags.Contains(tag))
208 processedTags.Add(tag);
209 var matchInSelf = variantAi.Elements().FirstOrDefault(e => e.GetAttributeString(
"tag",
null) == tag);
210 var matchInParent = baseAi.Elements().FirstOrDefault(e => e.GetAttributeString(
"tag",
null) == tag);
211 if (matchInSelf !=
null && matchInParent !=
null)
213 aiTarget.ReplaceWith(
new XElement(matchInSelf));
222 doc = XMLExtensions.TryLoadXml(Path);
225 DebugConsole.ThrowError(
"Main element null! Failed to load character params.");
229 if (!variantOf.IsEmpty)
232 #warning TODO: determine that CreateVariantXML is equipped to do this
235 var parentElement = (XContainer)oldElement.
Parent ??
doc; oldElement.Remove(); parentElement.Add(newRoot);
248 public bool Save(
string fileNameWithoutExtension =
null)
253 return base.Save(fileNameWithoutExtension,
new XmlWriterSettings
256 OmitXmlDeclaration =
true,
257 NewLineOnAttributes =
false
261 public override bool Reset(
bool forceReload =
false)
272 public static bool CompareGroup(Identifier group1, Identifier group2) => group1 != Identifier.Empty && group2 != Identifier.Empty && group1 == group2;
278 DebugConsole.ThrowError(
"Main element null, cannot create sub params!");
283 if (healthElement !=
null)
289 DebugConsole.ThrowError($
"No health parameters defined for character \"{(SpeciesName)}\".");
332 public bool Deserialize(XElement element =
null,
bool alsoChildren =
true,
bool recursive =
true,
bool loadDefaultValues =
true)
334 if (base.Deserialize(element))
339 SpeciesName = element.GetAttributeIdentifier(
"name",
"[NAME NOT GIVEN]");
343 SubParams.ForEach(p => p.Deserialize(recursive));
350 public bool Serialize(XElement element =
null,
bool alsoChildren =
true,
bool recursive =
true)
352 if (base.Serialize(element))
356 SubParams.ForEach(p => p.Serialize(recursive));
366 base.AddToEditor(editor);
369 SubParams.ForEach(s => s.AddToEditor(editor, recursive));
389 private void AddEmitter(
string type)
399 case "damageemitter":
402 default:
throw new NotImplementedException(type);
414 if (subParam ==
null || subParam.Element ==
null || subParam.Element.Parent ==
null) {
return false; }
415 if (collection !=
null && !collection.Contains(subParam)) {
return false; }
416 if (!
SubParams.Contains(subParam)) {
return false; }
417 collection?.Remove(subParam);
419 subParam.Element.Remove();
423 protected bool TryAddSubParam<T>(
ContentXElement element, Func<ContentXElement, CharacterParams, T> constructor, out T subParam, IList<T> collection =
null, Func<IList<T>,
bool> filter =
null) where T :
SubParam
425 subParam = constructor(element,
this);
426 if (collection !=
null && filter !=
null)
428 if (filter(collection)) {
return false; }
432 collection?.Add(subParam);
433 return subParam !=
null;
439 public override string Name =>
"Sound";
442 public string File {
get;
private set; }
446 public SoundType
State {
get;
private set; }
450 public float Range {
get;
private set; }
453 public float Volume {
get;
private set; }
458 get =>
TagSet.ConvertToString();
459 private set =>
TagSet = value.ToIdentifiers().ToImmutableHashSet();
462 public ImmutableHashSet<Identifier>
TagSet {
get;
private set; } = ImmutableHashSet<Identifier>.Empty;
467 if (genderFallback != Identifier.Empty && genderFallback !=
"None")
481 if (name ==
null &&
Element !=
null)
483 name =
Element.
Name.ToString().FormatCamelCaseWithSpaces();
530 public override string Name =>
"Health";
545 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How easily the character heals from the bleeding wounds. Default 0 (no extra healing)."),
Editable(MinValueFloat = 0, MaxValueFloat = 100, DecimalCount = 2)]
548 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How easily the character heals from the burn wounds. Default 0 (no extra healing)."),
Editable(MinValueFloat = 0, MaxValueFloat = 100, DecimalCount = 2)]
575 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Severing legs doesn't work with most characters, because we'd need to take that into account with the walking animations and the standing position of the main collider etc. But there might be cases where you'll want to override this default."),
Editable]
584 private ImmutableHashSet<Identifier> _immunityIdentifiers;
590 return _immunityIdentifiers;
602 float newCrushDepth = -
CrushDepth * Physics.DisplayToRealWorldRatio + 1000;
603 DebugConsole.AddWarning($
"Character \"{character.SpeciesName}\" has a negative crush depth. "+
604 "Previously the crush depths were defined as display units (e.g. -30000 would correspond to 300 meters below the level), "+
605 "but now they're in meters (e.g. 3000 would correspond to a depth of 3000 meters displayed on the nav terminal). "+
606 $
"Changing the crush depth from {CrushDepth} to {newCrushDepth}.",
617 public override string Name =>
"Item";
625 public override string Name =>
"Inventory";
627 [
Serialize(
"Any, Any",
IsPropertySaveable.Yes, description:
"Which slots the inventory holds? Accepted types: None, Any, RightHand, LeftHand, Head, InnerClothes, OuterClothes, Headset, and Card."),
Editable()]
628 public string Slots {
get;
private set; }
636 public List<InventoryItem>
Items {
get;
private set; } =
new List<InventoryItem>();
640 foreach (var itemElement
in element.GetChildElements(
"item"))
650 if (
Element ==
null) {
return; }
652 var element =
CreateElement(
"item",
new XAttribute(
"identifier", identifier));
664 public override string Name =>
"AI";
670 public float Sight {
get;
private set; }
675 [
Serialize(-1.0f,
IsPropertySaveable.Yes, description:
"Hard limit to how far the character can spot targets from, regardless of the sight/hearing or how visible or how much noise the target is making. Not used if set to negative."),
Editable]
678 [
Serialize(100f,
IsPropertySaveable.Yes, description:
"How much the targeting priority increases each time the character takes damage. Works like the greed value, described above. The default value is 100."),
Editable(minValue: -1000f, maxValue: 1000f)]
681 [
Serialize(10f,
IsPropertySaveable.Yes, description:
"How much the targeting priority increases each time the character does damage to the target. The actual priority adjustment is calculated based on the damage percentage multiplied by the greed value. The default value is 10, which means the priority will increase by 1 every time the character does damage 10% of the target's current health. If the damage is 50%, then the priority increase is 5."),
Editable(minValue: 0f, maxValue: 1000f)]
684 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"If the health drops below this threshold, the character flees. In percentages."),
Editable(minValue: 0f, maxValue: 100f)]
687 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Does the character attack when provoked? When enabled, overrides the predefined targeting state with Attack and increases the priority of it."),
Editable()]
693 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How much damage is required for single attack to trigger avoiding/releasing targets."),
Editable(minValue: 0f, maxValue: 1000f)]
696 [
Serialize(3f,
IsPropertySaveable.Yes, description:
"How long the creature avoids gunfire. Also used when the creature is unlatched."),
Editable(minValue: 0f, maxValue: 100f)]
699 [
Serialize(20f,
IsPropertySaveable.Yes, description:
"How long the creature flees before returning to normal state. When the creature sees the target or is being chased, it will always flee, if it's in the flee state."),
Editable(minValue: 0f, maxValue: 100f)]
711 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"If enabled, the character chooses randomly from the available attacks. The priority is used as a weight for weighted random."),
Editable]
714 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Does the creature know how to open doors (still requires a proper ID card). Humans can always open doors (They don't use this AI definition)."),
Editable]
717 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Unlike human AI, monsters normally only use pathfinding when they are inside the submarine. When this is enabled, the monsters can also use pathfinding to get inside the sub. In practice, via doors and hatches."),
Editable]
723 [
Serialize(
true,
IsPropertySaveable.Yes,
"Is the creature allowed to navigate from and into the depths of the abyss? When enabled, the creatures will try to avoid the depths."),
Editable]
735 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Initial aggression used in the circle attack pattern (0-100). The aggression affects how close and how fast to the target the monster circles."),
Editable]
738 [
Serialize(100f,
IsPropertySaveable.Yes, description:
"Maximum aggression used in the circle attack pattern (0-100). The aggression affects how close and how fast to the target the monster circles."),
Editable]
741 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How quickly the aggression level increases from StartAggression to MaxAggression when using the circle attack pattern. Artificial amount, applied once per attack cycle."),
Editable]
748 [
Serialize(0f,
IsPropertySaveable.Yes,
"How likely it is that the creature plays dead (= ragdolls) while idling? Only allowed inside a sub (not in the open waters). Evaluated once, when the creature spawns."),
Editable]
751 public IEnumerable<TargetParams>
Targets => targets;
752 private readonly List<TargetParams> targets =
new List<TargetParams>();
756 if (element ==
null) {
return; }
770 DebugConsole.AddWarning($
"Trying to add multiple targets with the same tag ('{tag}') defined! Only the first will be used!", targetElement.
ContentPackage);
774 target = AddTarget(targetElement);
776 return target !=
null;
782 private TargetParams AddTarget(ContentXElement targetElement)
784 var target =
new TargetParams(targetElement,
Character);
793 TryAddNewTarget(tag.ToIdentifier(), state, priority, out targetParams);
803 if (TryAddTarget(element, out targetParams))
818 if (tag ==
null) {
return false; }
819 return targets.Any(t => t.Tag == tag);
824 public IEnumerable<TargetParams>
GetMatchingTargets(Func<TargetParams, bool> predicate) => targets.Where(predicate);
832 public bool TryGetTargets(Identifier target, out IEnumerable<TargetParams> targetParams)
835 return targetParams.Any();
841 return targetParams.Any();
847 return targetParams !=
null;
853 return targetParams !=
null;
859 if (tags ==
null || tags.None()) {
return false; }
861 foreach (var potentialTarget
in targets)
863 if (potentialTarget.Priority > priority)
865 if (tags.Any(t => t == potentialTarget.Tag))
867 target = potentialTarget;
868 priority = target.Priority;
872 return target !=
null;
878 public override string Name =>
"Target";
880 [
Serialize(
"",
IsPropertySaveable.Yes, description:
"Can be an item tag, species name or something else. Examples: decoy, provocative, light, dead, human, crawler, wall, nasonov, sonar, door, stronger, weaker, light, human, room..."),
Editable()]
881 public Identifier
Tag {
get;
private set; }
886 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"What base priority is given to the target?"),
Editable(minValue: 0f, maxValue: 1000f, ValueStep = 1, DecimalCount = 0)]
889 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Generic distance that can be used for different purposes depending on the state. E.g. in Avoid state this defines the distance that the character tries to keep to the target. If the distance is 0, it's not used."),
Editable(MinValueFloat = 0, ValueStep = 10, DecimalCount = 0)]
892 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Used for defining the attack distance for PassiveAggressive and Aggressive states. If the distance is 0, it's not used."),
Editable(MinValueFloat = 0, ValueStep = 10, DecimalCount = 0)]
895 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Generic timer that can be used for different purposes depending on the state. E.g. in Observe state this defines how long the character in general keeps staring the targets (Some random is always applied)."),
Editable]
913 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Should the target be ignored if it's inside a different submarine than us? Normally only some targets are ignored when they are not inside the same sub."),
Editable]
919 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"A generic threshold. For example, how much damage the protected target should take from an attacker before the creature starts defending it."),
Editable]
931 [
Serialize(-1.0f,
IsPropertySaveable.Yes, description:
"Maximum distance at which the monster can perceive the target, regardless of the sight/hearing or how visible or how much noise the target is making. Not used if set to negative."),
Editable]
934 [
Serialize(
"0.0, 0.0",
IsPropertySaveable.Yes, description:
"A generic offset. Used for example for offsetting the react distance (vector length) and for offsetting the target position when a guardian flees to a pod."),
Editable]
935 public Vector2
Offset {
get;
private set; }
940 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"If enabled, the AI will give more priority to targets close to the horizontal middle of the sub. Only applies to walls, hulls, and items like sonar. Circle and Sweep always does this regardless of this property."),
Editable]
944 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"Use to define a distance at which the creature starts the sweeping movement."),
Editable(MinValueFloat = 0, MaxValueFloat = 10000, ValueStep = 1, DecimalCount = 0)]
947 [
Serialize(10f,
IsPropertySaveable.Yes, description:
"How much the sweep affects the steering?"),
Editable(MinValueFloat = 0, MaxValueFloat = 100, ValueStep = 1f, DecimalCount = 1)]
950 [
Serialize(1f,
IsPropertySaveable.Yes, description:
"How quickly the sweep direction changes. Uses the sine wave pattern."),
Editable(MinValueFloat = 0, MaxValueFloat = 10, ValueStep = 0.1f, DecimalCount = 2)]
955 [
Serialize(5000f,
IsPropertySaveable.Yes, description:
"How close to the target the character should be, before they start using the circle pattern instead of directional approaching."),
Editable(MinValueFloat = 0f, MaxValueFloat = 20000f)]
958 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"Normally the target size is taken into account when calculating the distance to the target. Set this true to skip that.")]
961 [
Serialize(1f,
IsPropertySaveable.Yes, description:
"Determines the rate how quickly the target movement position is rotated towards the attack target. The actual rotation is calculated once per each attack cycle, based on the current aggression level."),
Editable(MinValueFloat = 0f, MaxValueFloat = 100f)]
964 [
Serialize(
false,
IsPropertySaveable.Yes, description:
"When enabled, the circle rotation speed can change when the target is far. When this setting is disabled (default), the character will head directly towards the target when it's too far."),
Editable]
967 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How much the turn speed can differ between attack cycles (stays constant during the cycle)"),
Editable(MinValueFloat = 0f, MaxValueFloat = 1f)]
970 [
Serialize(5f,
IsPropertySaveable.Yes, description:
"Affects how close to the target the character has to be before the strike phase of the circle behavior triggers. In the strike phase, the creature moves directly towards the target."),
Editable(MinValueFloat = 0f, MaxValueFloat = 10f)]
973 [
Serialize(0f,
IsPropertySaveable.Yes, description:
"How much the target position is offset at maximum. Low values make the character hit the target earlier/always, higher values make it miss the target when the aggression intensity is low (early in the encounter)."),
Editable(MinValueFloat = 0f, MaxValueFloat = 50f)]
980 public List<PropertyConditional>
Conditionals {
get;
private set; } =
new List<PropertyConditional>();
987 foreach (var subElement
in element.Elements())
989 switch (subElement.Name.ToString().ToLowerInvariant())
1003 return new XElement(
"target",
1004 new XAttribute(
"tag", tag),
1005 new XAttribute(
"state", state),
1012 public virtual string Name {
get;
set; }
1015 public List<SubParam>
SubParams {
get;
set; } =
new List<SubParam>();
1034 SubParams.ForEach(sp => sp.Deserialize(
true));
1044 SubParams.ForEach(sp => sp.Serialize(
true));
1058 if (subParam ==
null || subParam.Element ==
null || subParam.Element.Parent ==
null) {
return false; }
1059 if (collection !=
null && !collection.Contains(subParam)) {
return false; }
1060 if (!
SubParams.Contains(subParam)) {
return false; }
1061 collection?.Remove(subParam);
1063 subParam.Element.Remove();
1074 SubParams.ForEach(sp => sp.AddToEditor(editor,
true, titleFont: titleFont ?? GUIStyle.SmallFont));
1080 CanBeFocused =
false
bool TryGetHighestPriorityTarget(Character target, out TargetParams targetParams)
bool TryAddEmptyTarget(out TargetParams targetParams)
bool HasTag(Identifier tag)
float PlayDeadProbability
float FleeHealthThreshold
bool TryGetHighestPriorityTarget(Identifier target, out TargetParams targetParams)
bool TryGetTargets(Identifier target, out IEnumerable< TargetParams > targetParams)
TargetParams GetHighestPriorityTarget(Identifier target)
bool TryGetTargets(Character target, out IEnumerable< TargetParams > targetParams)
float MaxPerceptionDistance
IEnumerable< TargetParams > Targets
bool EnforceAggressiveBehaviorForMissions
IEnumerable< TargetParams > GetMatchingTargets(Func< TargetParams, bool > predicate)
IEnumerable< TargetParams > GetTargets(Character target)
bool TryAddNewTarget(string tag, AIState state, float priority, out TargetParams targetParams)
bool TryGetHighestPriorityTarget(IEnumerable< Identifier > tags, out TargetParams target)
bool UsePathFindingToGetInside
TargetParams GetHighestPriorityTarget(Character target)
AIParams(ContentXElement element, CharacterParams character)
float AggressionCumulation
bool RemoveTarget(TargetParams target)
IEnumerable< TargetParams > GetTargets(Identifier target)
bool TryAddNewTarget(Identifier tag, AIState state, float priority, out TargetParams targetParams)
float PoisonVulnerability
IEnumerable< Identifier > ImmunityIdentifiers
float ConstantHealthRegeneration
HealthParams(ContentXElement element, CharacterParams character)
bool ApplyMovementPenalties
bool ApplyAfflictionColors
float HealthRegenerationWhenEating
InventoryItem(ContentXElement element, CharacterParams character)
List< InventoryItem > Items
bool RemoveItem(InventoryItem item)
InventoryParams(ContentXElement element, CharacterParams character)
void AddItem(string identifier=null)
bool HighQualityCollisionDetection
ParticleParams(ContentXElement element, CharacterParams character)
SoundParams(ContentXElement element, CharacterParams character)
ImmutableHashSet< Identifier > TagSet
virtual bool Deserialize(bool recursive=true)
ContentXElement CreateElement(string name, params object[] attrs)
CharacterParams Character
SubParam(ContentXElement element, CharacterParams character)
SerializableEntityEditor SerializableEntityEditor
bool RemoveSubParam< T >(T subParam, IList< T > collection=null)
virtual void AddToEditor(ParamsEditor editor, bool recursive=true, int space=0, GUIFont titleFont=null)
virtual bool Serialize(bool recursive=true)
List< SubParam > SubParams
Dictionary< Identifier, SerializableProperty > SerializableProperties
float CircleRandomRotationFactor
bool DynamicCircleRotationSpeed
float CircleRotationSpeed
TargetParams(string tag, AIState state, float priority, CharacterParams character)
List< PropertyConditional > Conditionals
Conditionals that must be met for the character to be able to use these targeting parameters.
static ContentXElement CreateNewElement(CharacterParams character, string tag, AIState state, float priority)
float CircleMaxRandomOffset
static ContentXElement CreateNewElement(CharacterParams character, Identifier tag, AIState state, float priority)
bool IgnoreIfNotInSameSub
float PerceptionDistanceMultiplier
TargetParams(ContentXElement element, CharacterParams character)
float CircleStartDistance
float MaxPerceptionDistance
float CircleStrikeDistanceMultiplier
Contains character data that should be editable in the character editor.
bool RemoveBloodEmitter(ParticleParams emitter)
bool HideInThermalGoggles
bool RemoveInventory(InventoryParams inventory)
bool RemoveSound(SoundParams soundParams)
bool TryAddSubParam< T >(ContentXElement element, Func< ContentXElement, CharacterParams, T > constructor, out T subParam, IList< T > collection=null, Func< IList< T >, bool > filter=null)
bool RemoveDamageEmitter(ParticleParams emitter)
AIParams AI
Parameters for EnemyAIController. Not used by HumanAIController.
readonly List< ParticleParams > DamageEmitters
override ContentXElement? MainElement
readonly List< SoundParams > Sounds
readonly CharacterFile File
Identifier NonHuskedSpecies
bool Save(string fileNameWithoutExtension=null)
override string GetName()
bool Deserialize(XElement element=null, bool alsoChildren=true, bool recursive=true, bool loadDefaultValues=true)
static XElement CreateVariantXml(ContentXElement variantXML, ContentXElement baseXML)
bool RemoveSubParam< T >(T subParam, IList< T > collection=null)
readonly List< ParticleParams > GibEmitters
Identifier DespawnContainer
void AddToEditor(ParamsEditor editor, bool alsoChildren=true, bool recursive=true, int space=0)
float AISlowTurretPriority
readonly List< ParticleParams > BloodEmitters
CharacterParams(CharacterFile file)
bool Serialize(XElement element=null, bool alsoChildren=true, bool recursive=true)
static bool CompareGroup(Identifier group1, Identifier group2)
float BleedParticleMultiplier
bool HasTag(Identifier tag)
readonly List< InventoryParams > Inventories
string BleedParticleWater
readonly List< SubParam > SubParams
Identifier SpeciesTranslationOverride
override bool Reset(bool forceReload=false)
bool RemoveGibEmitter(ParticleParams emitter)
static CharacterPrefab FindBySpeciesName(Identifier speciesName)
ContentXElement ConfigElement
readonly ContentPackage ContentPackage
void Add(ContentXElement elem)
string? GetAttributeString(string key, string? def)
Identifier[] GetAttributeIdentifierArray(Identifier[] def, params string[] keys)
ContentPackage? ContentPackage
IEnumerable< ContentXElement > GetChildElements(string name)
ContentXElement? GetChildElement(string name)
Identifier GetAttributeIdentifier(string key, string def)
virtual void UpdatePath(ContentPath fullPath)
ContentXElement CreateElement(string name, params object[] attrs)
ContentXElement OriginalElement
RectTransform RectTransform
GUIFrame Content
A frame that contains the contents of the listbox. The frame itself is not rendered.
Conditionals are used by some in-game mechanics to require one or more conditions to be met for those...
static IEnumerable< PropertyConditional > FromXElement(ContentXElement element, Predicate< XAttribute >? predicate=null)
static Dictionary< Identifier, SerializableProperty > DeserializeProperties(object obj, XElement element=null)
static void SerializeProperties(ISerializableEntity obj, XElement element, bool saveIfDefault=false, bool ignoreEditable=false)