(3dc4135ce) v0.9.5.1

This commit is contained in:
Regalis
2019-11-21 18:22:25 +01:00
parent b39922a074
commit 5c95c53118
287 changed files with 12655 additions and 5048 deletions
@@ -11,7 +11,7 @@ using System.Xml.Linq;
namespace Barotrauma
{
public enum Gender { None, Male, Female };
public enum Race { None, White, Black, Asian };
public enum Race { None, White, Black, Brown, Asian };
// TODO: Generating the HeadInfo could be simplified.
partial class CharacterInfo
@@ -33,8 +33,10 @@ namespace Barotrauma
{
_headSpriteId = (int)headSpriteRange.X;
}
GetSpriteSheetIndex();
}
}
public Vector2? SheetIndex { get; private set; }
public Vector2 headSpriteRange;
public Gender gender;
public Race race;
@@ -51,9 +53,16 @@ namespace Barotrauma
public HeadInfo() { }
public HeadInfo(int headId)
public HeadInfo(int headId, Gender gender, Race race, int hairIndex = 0, int beardIndex = 0, int moustacheIndex = 0, int faceAttachmentIndex = 0)
{
_headSpriteId = Math.Max(headId, 1);
this.gender = gender;
this.race = race;
HairIndex = hairIndex;
BeardIndex = beardIndex;
MoustacheIndex = moustacheIndex;
FaceAttachmentIndex = faceAttachmentIndex;
GetSpriteSheetIndex();
}
public void ResetAttachmentIndices()
@@ -63,6 +72,21 @@ namespace Barotrauma
MoustacheIndex = -1;
FaceAttachmentIndex = -1;
}
private void GetSpriteSheetIndex()
{
if (heads != null && heads.Any())
{
var matchingHead = heads.Keys.FirstOrDefault(h => h.Gender == gender && h.Race == race && h.ID == _headSpriteId);
if (matchingHead != null)
{
if (heads.TryGetValue(matchingHead, out Vector2 index))
{
SheetIndex = index;
}
}
}
}
}
private HeadInfo head;
@@ -86,6 +110,43 @@ namespace Barotrauma
}
}
public Dictionary<HeadPreset, Vector2> Heads
{
get
{
if (heads == null)
{
LoadHeadPresets();
}
return heads;
}
}
private static Dictionary<HeadPreset, Vector2> heads;
public class HeadPreset : ISerializableEntity
{
[Serialize(Race.None, false)]
public Race Race { get; private set; }
[Serialize(Gender.None, false)]
public Gender Gender { get; private set; }
[Serialize(0, false)]
public int ID { get; private set; }
[Serialize("0,0", false)]
public Vector2 SheetIndex { get; private set; }
public string Name => $"Head Preset {Race} {Gender} {ID}";
public Dictionary<string, SerializableProperty> SerializableProperties { get; private set; }
public HeadPreset(XElement element)
{
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
}
}
private static ushort idCounter;
public string Name;
@@ -158,6 +219,12 @@ namespace Barotrauma
{
LoadHeadSprite();
}
#if CLIENT
if (headSprite != null)
{
CalculateHeadPosition(headSprite);
}
#endif
return headSprite;
}
private set
@@ -170,6 +237,8 @@ namespace Barotrauma
}
}
public bool OmitJobInPortraitClothing;
private Sprite portrait;
public Sprite Portrait
{
@@ -223,7 +292,7 @@ namespace Barotrauma
{
if (attachmentSprites == null)
{
LoadAttachmentSprites();
LoadAttachmentSprites(OmitJobInPortraitClothing);
}
return attachmentSprites;
}
@@ -350,7 +419,7 @@ namespace Barotrauma
public bool IsAttachmentsLoaded => HairIndex > -1 && BeardIndex > -1 && MoustacheIndex > -1 && FaceAttachmentIndex > -1;
// Used for creating the data
public CharacterInfo(string speciesName, string name = "", JobPrefab jobPrefab = null, string ragdollFileName = null)
public CharacterInfo(string speciesName, string name = "", JobPrefab jobPrefab = null, string ragdollFileName = null, int variant = 0)
{
if (speciesName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
@@ -372,7 +441,7 @@ namespace Barotrauma
Head.race = GetRandomRace();
CalculateHeadSpriteRange();
Head.HeadSpriteId = GetRandomHeadID();
Job = (jobPrefab == null) ? Job.Random(Rand.RandSync.Server) : new Job(jobPrefab);
Job = (jobPrefab == null) ? Job.Random(Rand.RandSync.Server) : new Job(jobPrefab, variant);
if (!string.IsNullOrEmpty(name))
{
Name = name;
@@ -534,11 +603,38 @@ namespace Barotrauma
Enum.TryParse(w.GetAttributeString("race", "None"), true, out Race r) && r == Head.race);
}
private void LoadHeadPresets()
{
if (CharacterConfigElement == null) { return; }
heads = new Dictionary<HeadPreset, Vector2>();
var headsElement = CharacterConfigElement.GetChildElement("heads");
if (headsElement != null)
{
foreach (var head in headsElement.GetChildElements("head"))
{
var preset = new HeadPreset(head);
heads.Add(preset, preset.SheetIndex);
}
}
}
private void CalculateHeadSpriteRange()
{
if (CharacterConfigElement == null) { return; }
Head.headSpriteRange = CharacterConfigElement.GetAttributeVector2("headidrange", Vector2.Zero);
// If range is defined, we use it as it is
// If the range is defined, we use it as it is
if (Head.headSpriteRange != Vector2.Zero) { return; }
if (heads == null)
{
LoadHeadPresets();
}
// If there are any head presets defined, use them.
if (heads.Any())
{
var ids = heads.Keys.Where(h => h.Race == Race && h.Gender == Gender).Select(w => w.ID);
ids = ids.OrderBy(id => id);
Head.headSpriteRange = new Vector2(ids.First(), ids.Last());
}
// Else we calculate the range from the wearables.
if (Head.headSpriteRange == Vector2.Zero)
{
@@ -580,23 +676,13 @@ namespace Barotrauma
{
gender = Gender.None;
}
head = new HeadInfo(headID)
{
race = race,
gender = gender,
HairIndex = hairIndex,
BeardIndex = beardIndex,
MoustacheIndex = moustacheIndex,
FaceAttachmentIndex = faceAttachmentIndex
};
head = new HeadInfo(headID, gender, race, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
CalculateHeadSpriteRange();
ReloadHeadAttachments();
}
public void LoadHeadSprite()
{
// TODO: use ragdollparams instead?
foreach (XElement limbElement in Ragdoll.MainElement.Elements())
{
if (limbElement.GetAttributeString("type", "").ToLowerInvariant() != "head") { continue; }
@@ -649,7 +735,8 @@ namespace Barotrauma
{
if (hairs == null)
{
hairs = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables), WearableType.Hair), WearableType.Hair);
float commonness = Gender == Gender.Female ? 0.05f : 0.2f;
hairs = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables), WearableType.Hair), WearableType.Hair, commonness);
}
if (beards == null)
{
@@ -701,10 +788,10 @@ namespace Barotrauma
Head.FaceAttachmentIndex = faceAttachments.IndexOf(Head.FaceAttachment);
}
List<XElement> AddEmpty(IEnumerable<XElement> elements, WearableType type)
List<XElement> AddEmpty(IEnumerable<XElement> elements, WearableType type, float commonness = 1)
{
// Let's add an empty element so that there's a chance that we don't get any actual element -> allows bald and beardless guys, for example.
var emptyElement = new XElement("EmptyWearable", type.ToString());
var emptyElement = new XElement("EmptyWearable", type.ToString(), new XAttribute("commonness", commonness));
var list = new List<XElement>() { emptyElement };
list.AddRange(elements);
return list;
@@ -743,7 +830,7 @@ namespace Barotrauma
}
}
partial void LoadAttachmentSprites();
partial void LoadAttachmentSprites(bool omitJob);
// TODO: change the formula so that it's not linear and so that it takes into account the usefulness of the skill
// -> give a weight to each skill, because some are much more valuable than others?