v0.12.0.2

This commit is contained in:
Joonas Rikkonen
2021-02-10 17:08:21 +02:00
parent 5c80a59bdd
commit 694cdfee7b
353 changed files with 12897 additions and 5028 deletions
@@ -66,8 +66,13 @@ namespace Barotrauma
protected static Dictionary<string, Dictionary<string, AnimationParams>> allAnimations = new Dictionary<string, Dictionary<string, AnimationParams>>();
private float _movementSpeed;
[Serialize(1.0f, true), Editable(DecimalCount = 2, MinValueFloat = 0, MaxValueFloat = Ragdoll.MAX_SPEED, ValueStep = 0.1f)]
public float MovementSpeed { get; set; }
public float MovementSpeed
{
get => _movementSpeed;
set => _movementSpeed = value;
}
[Serialize(1.0f, true, description: "The speed of the \"animation cycle\", i.e. how fast the character takes steps or moves the tail/legs/arms (the outcome depends what the clip is about)"),
Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
@@ -110,11 +115,10 @@ namespace Barotrauma
[Serialize(AnimationType.NotDefined, true), Editable]
public virtual AnimationType AnimationType { get; protected set; }
public static string GetDefaultFileName(string speciesName, AnimationType animType) => $"{speciesName.CapitaliseFirstInvariant()}{animType.ToString()}";
public static string GetDefaultFile(string speciesName, AnimationType animType, ContentPackage contentPackage = null)
=> Path.Combine(GetFolder(speciesName, contentPackage), $"{GetDefaultFileName(speciesName, animType)}.xml");
public static string GetDefaultFileName(string speciesName, AnimationType animType) => $"{speciesName.CapitaliseFirstInvariant()}{animType}";
public static string GetDefaultFile(string speciesName, AnimationType animType) => Path.Combine(GetFolder(speciesName), $"{GetDefaultFileName(speciesName, animType)}.xml");
public static string GetFolder(string speciesName, ContentPackage contentPackage = null)
public static string GetFolder(string speciesName)
{
CharacterPrefab prefab = CharacterPrefab.FindBySpeciesName(speciesName);
if (prefab?.XDocument == null)
@@ -132,7 +136,7 @@ namespace Barotrauma
{
folder = Path.Combine(Path.GetDirectoryName(filePath), "Animations");
}
return folder;
return folder.CleanUpPathCrossPlatform(true);
}
/// <summary>
@@ -163,7 +167,16 @@ namespace Barotrauma
return Enum.TryParse(typeString, out AnimationType fileType) && fileType == type;
}
public static T GetDefaultAnimParams<T>(string speciesName, AnimationType animType) where T : AnimationParams, new() => GetAnimParams<T>(speciesName, animType, GetDefaultFileName(speciesName, animType));
public static T GetDefaultAnimParams<T>(Character character, AnimationType animType) where T : AnimationParams, new()
{
string speciesName = character.VariantOf ?? character.SpeciesName;
if (character.VariantOf != null && character.Params.VariantFile?.Root?.GetChildElement("animations")?.GetAttributeString("folder", null) != null)
{
// Use the overridden animations defined in the variant definition file.
speciesName = character.SpeciesName;
}
return GetAnimParams<T>(speciesName, animType, GetDefaultFileName(speciesName, animType));
}
/// <summary>
/// If the file name is left null, default file is selected. If fails, will select the default file. Note: Use the filename without the extensions, don't use the full path!
@@ -7,11 +7,11 @@ namespace Barotrauma
{
public static FishWalkParams GetDefaultAnimParams(Character character)
{
return Check(character) ? GetDefaultAnimParams<FishWalkParams>(character.SpeciesName, AnimationType.Walk) : Empty;
return Check(character) ? GetDefaultAnimParams<FishWalkParams>(character, AnimationType.Walk) : Empty;
}
public static FishWalkParams GetAnimParams(Character character, string fileName = null)
{
return Check(character) ? GetAnimParams<FishWalkParams>(character.SpeciesName, AnimationType.Walk, fileName) : Empty;
return Check(character) ? GetAnimParams<FishWalkParams>(character.VariantOf ?? character.SpeciesName, AnimationType.Walk, fileName) : Empty;
}
protected static FishWalkParams Empty = new FishWalkParams();
@@ -23,11 +23,11 @@ namespace Barotrauma
{
public static FishRunParams GetDefaultAnimParams(Character character)
{
return Check(character) ? GetDefaultAnimParams<FishRunParams>(character.SpeciesName, AnimationType.Run) : Empty;
return Check(character) ? GetDefaultAnimParams<FishRunParams>(character, AnimationType.Run) : Empty;
}
public static FishRunParams GetAnimParams(Character character, string fileName = null)
{
return Check(character) ? GetAnimParams<FishRunParams>(character.SpeciesName, AnimationType.Run, fileName) : Empty;
return Check(character) ? GetAnimParams<FishRunParams>(character.VariantOf ?? character.SpeciesName, AnimationType.Run, fileName) : Empty;
}
protected static FishRunParams Empty = new FishRunParams();
@@ -37,10 +37,10 @@ namespace Barotrauma
class FishSwimFastParams : FishSwimParams
{
public static FishSwimFastParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<FishSwimFastParams>(character.SpeciesName, AnimationType.SwimFast);
public static FishSwimFastParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<FishSwimFastParams>(character, AnimationType.SwimFast);
public static FishSwimFastParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<FishSwimFastParams>(character.SpeciesName, AnimationType.SwimFast, fileName);
return GetAnimParams<FishSwimFastParams>(character.VariantOf ?? character.SpeciesName, AnimationType.SwimFast, fileName);
}
public override void StoreSnapshot() => StoreSnapshot<FishSwimFastParams>();
@@ -48,10 +48,10 @@ namespace Barotrauma
class FishSwimSlowParams : FishSwimParams
{
public static FishSwimSlowParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<FishSwimSlowParams>(character.SpeciesName, AnimationType.SwimSlow);
public static FishSwimSlowParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<FishSwimSlowParams>(character, AnimationType.SwimSlow);
public static FishSwimSlowParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<FishSwimSlowParams>(character.SpeciesName, AnimationType.SwimSlow, fileName);
return GetAnimParams<FishSwimSlowParams>(character.VariantOf ?? character.SpeciesName, AnimationType.SwimSlow, fileName);
}
public override void StoreSnapshot() => StoreSnapshot<FishSwimSlowParams>();
@@ -4,7 +4,7 @@ namespace Barotrauma
{
class HumanWalkParams : HumanGroundedParams
{
public static HumanWalkParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanWalkParams>(character.SpeciesName, AnimationType.Walk);
public static HumanWalkParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanWalkParams>(character, AnimationType.Walk);
public static HumanWalkParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<HumanWalkParams>(character.SpeciesName, AnimationType.Walk, fileName);
@@ -15,7 +15,7 @@ namespace Barotrauma
class HumanRunParams : HumanGroundedParams
{
public static HumanRunParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanRunParams>(character.SpeciesName, AnimationType.Run);
public static HumanRunParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanRunParams>(character, AnimationType.Run);
public static HumanRunParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<HumanRunParams>(character.SpeciesName, AnimationType.Run, fileName);
@@ -26,7 +26,7 @@ namespace Barotrauma
class HumanSwimFastParams: HumanSwimParams
{
public static HumanSwimFastParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanSwimFastParams>(character.SpeciesName, AnimationType.SwimFast);
public static HumanSwimFastParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanSwimFastParams>(character, AnimationType.SwimFast);
public static HumanSwimFastParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<HumanSwimFastParams>(character.SpeciesName, AnimationType.SwimFast, fileName);
@@ -38,7 +38,7 @@ namespace Barotrauma
class HumanSwimSlowParams : HumanSwimParams
{
public static HumanSwimSlowParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanSwimSlowParams>(character.SpeciesName, AnimationType.SwimSlow);
public static HumanSwimSlowParams GetDefaultAnimParams(Character character) => GetDefaultAnimParams<HumanSwimSlowParams>(character, AnimationType.SwimSlow);
public static HumanSwimSlowParams GetAnimParams(Character character, string fileName = null)
{
return GetAnimParams<HumanSwimSlowParams>(character.SpeciesName, AnimationType.SwimSlow, fileName);
@@ -78,6 +78,8 @@ namespace Barotrauma
public readonly string File;
public XDocument VariantFile { get; private set; }
public readonly List<SubParam> SubParams = new List<SubParam>();
public readonly List<SoundParams> Sounds = new List<SoundParams>();
public readonly List<ParticleParams> BloodEmitters = new List<ParticleParams>();
@@ -100,6 +102,32 @@ namespace Barotrauma
public bool Load()
{
bool success = base.Load(File);
if (doc.Root.IsCharacterVariant())
{
VariantFile = doc;
var original = CharacterPrefab.FindBySpeciesName(doc.Root.GetAttributeString("inherit", string.Empty));
success = Load(original.FilePath);
CreateSubParams();
TryLoadOverride(this, VariantFile.Root, SerializableProperties);
foreach (XElement subElement in VariantFile.Root.Elements())
{
var matchingParams = SubParams.FirstOrDefault(p => p.Name.Equals(subElement.Name.ToString(), StringComparison.OrdinalIgnoreCase));
if (matchingParams != null)
{
TryLoadOverride(matchingParams, subElement, matchingParams.SerializableProperties);
// TODO: Make recursive? In practice we don't have to go deeper than this, but the implementation would be a lot cleaner with recursion.
foreach (XElement subSubElement in subElement.Elements())
{
matchingParams = matchingParams.SubParams.FirstOrDefault(p => p.Name.Equals(subSubElement.Name.ToString(), StringComparison.OrdinalIgnoreCase));
if (matchingParams != null)
{
TryLoadOverride(matchingParams, subSubElement, matchingParams.SerializableProperties);
}
}
}
}
return success;
}
if (string.IsNullOrEmpty(SpeciesName) && MainElement != null)
{
//backwards compatibility
@@ -111,6 +139,8 @@ namespace Barotrauma
public bool Save(string fileNameWithoutExtension = null)
{
// Disable saving variants for now. Making it work probably requires more work.
if (VariantFile != null) { return false; }
Serialize();
return base.Save(fileNameWithoutExtension, new XmlWriterSettings
{
@@ -181,7 +211,19 @@ namespace Barotrauma
}
}
public bool Deserialize(XElement element = null, bool alsoChildren = true, bool recursive = true)
private void TryLoadOverride(object parentObject, XElement element, Dictionary<string, SerializableProperty> properties)
{
foreach (var property in properties)
{
var matchingAttribute = element.GetAttribute(property.Key);
if (matchingAttribute != null)
{
property.Value.TrySetValue(parentObject, matchingAttribute.Value);
}
}
}
public bool Deserialize(XElement element = null, bool alsoChildren = true, bool recursive = true, bool loadDefaultValues = true)
{
if (base.Deserialize(element))
{
@@ -486,17 +528,21 @@ namespace Barotrauma
[Serialize(true, true, description: "Enforce aggressive behavior if the creature is spawned as a target of a monster mission."), Editable()]
public bool EnforceAggressiveBehaviorForMissions { get; private set; }
[Serialize(true, true, description: "Should the character target or ignore walls when it's outside the submarine. Doesn't have any effect if no target priority for walls is defined."), Editable()]
[Serialize(true, true, description: "Should the character target or ignore walls when it's outside the submarine."), Editable()]
public bool TargetOuterWalls { get; private set; }
[Serialize(false, true, description: "If enabled, the character chooses randomly from the available attacks. The priority is used as a weight for weighted random."), Editable()]
public bool RandomAttack { get; private set; }
[Serialize(false, true, description:"Can the character open doors and hatches without a proper id card? Only applies on humanoids.")]
public bool Infiltrate { get; private set; }
public IEnumerable<TargetParams> Targets => targets;
protected readonly List<TargetParams> targets = new List<TargetParams>();
public AIParams(XElement element, CharacterParams character) : base(element, character)
{
if (element == null) { return; }
element.GetChildElements("target").ForEach(t => TryAddTarget(t, out _));
element.GetChildElements("targetpriority").ForEach(t => TryAddTarget(t, out _));
}
@@ -588,10 +634,13 @@ namespace Barotrauma
public bool IgnoreContained { get; set; }
[Serialize(false, true, description: "Should the target be ignored while the creature is inside. Doesn't matter where the target is."), Editable]
public bool IgnoreWhileInside { get; set; }
public bool IgnoreInside { get; set; }
[Serialize(false, true, description: "Should the target be ignored while the creature is outside. Doesn't matter where the target is."), Editable]
public bool IgnoreWhileOutside { get; set; }
public bool IgnoreOutside { get; set; }
[Serialize(false, true)]
public bool IgnoreIncapacitated { get; set; }
[Serialize(0f, true, description: "Use to define a distance at which the creature starts the sweeping movement."), Editable(MinValueFloat = 0, MaxValueFloat = 10000, ValueStep = 1, DecimalCount = 0)]
public float SweepDistance { get; private set; }
@@ -602,6 +651,9 @@ namespace Barotrauma
[Serialize(1f, true, description: "How quickly the sweep direction changes. Uses the sine wave pattern."), Editable(MinValueFloat = 0, MaxValueFloat = 10, ValueStep = 0.1f, DecimalCount = 2)]
public float SweepSpeed { get; private set; }
[Serialize(0f, true, description: "How much damage the protected target should take from an attacker before the creature starts defending it.")]
public float Threshold { get; private set; }
public TargetParams(XElement element, CharacterParams character) : base(element, character) { }
public TargetParams(string tag, AIState state, float priority, CharacterParams character) : base(CreateNewElement(tag, state, priority), character) { }
@@ -44,14 +44,14 @@ namespace Barotrauma
protected virtual bool Deserialize(XElement element = null)
{
element = element ?? MainElement;
element ??= MainElement;
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
return SerializableProperties != null;
}
protected virtual bool Serialize(XElement element = null)
{
element = element ?? MainElement;
element ??= MainElement;
if (element == null)
{
DebugConsole.ThrowError("[EditableParams] The XML element is null!");
@@ -110,7 +110,7 @@ namespace Barotrauma
{
folder = Path.Combine(Path.GetDirectoryName(filePath), "Ragdolls") + Path.DirectorySeparatorChar;
}
return folder;
return folder.CleanUpPathCrossPlatform(correctFilenameCase: true);
}
public static T GetDefaultRagdollParams<T>(string speciesName) where T : RagdollParams, new() => GetRagdollParams<T>(speciesName, GetDefaultFileName(speciesName));
@@ -136,7 +136,7 @@ namespace Barotrauma
string folder = GetFolder(speciesName);
if (Directory.Exists(folder))
{
var files = Directory.GetFiles(folder);
List<string> files = Directory.GetFiles(folder).ToList();
if (files.None())
{
DebugConsole.ThrowError($"[RagdollParams] Could not find any ragdoll files from the folder: {folder}. Using the default ragdoll.");
@@ -364,6 +364,21 @@ namespace Barotrauma
}
}
#endif
private bool variantScaleApplied;
public void ApplyVariantScale(XDocument variantFile)
{
if (variantScaleApplied) { return; }
if (variantFile == null) { return; }
var scaleMultiplier = variantFile.Root.GetChildElement("ragdoll")?.GetAttributeFloat("scalemultiplier", 1f);
if (scaleMultiplier.HasValue)
{
JointScale *= scaleMultiplier.Value;
LimbScale *= scaleMultiplier.Value;
}
variantScaleApplied = true;
}
#endregion
#region Memento