[Feat] Тонкие спрайты снова в строю (#102)
* Revert "Hair Overhaul (#19298)"
This reverts commit 9491f322de.
# Conflicts:
# Resources/Textures/Mobs/Customization/human_hair.rsi/a.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/afro.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/afro2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/bigafro.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/cornrows2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/emofringe.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/keanu.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long3.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/meta.json
# Resources/Textures/Mobs/Customization/human_hair.rsi/modern.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/quiff.png
* add: возврат системы тонкоспрайтов
* fix: небольшие фиксы после реверта причесок
* add: старые текстуры для slim бодитайпа
* fix: фикс причесок после апстрима
@@ -5,12 +5,14 @@ using Content.Shared.Clothing;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.GameObjects.SpriteComponent;
|
||||
@@ -28,30 +30,31 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, string> TemporarySlotMap = new()
|
||||
{
|
||||
{"head", "HELMET"},
|
||||
{"eyes", "EYES"},
|
||||
{"ears", "EARS"},
|
||||
{"mask", "MASK"},
|
||||
{"outerClothing", "OUTERCLOTHING"},
|
||||
{Jumpsuit, "INNERCLOTHING"},
|
||||
{"neck", "NECK"},
|
||||
{"back", "BACKPACK"},
|
||||
{"belt", "BELT"},
|
||||
{"gloves", "HAND"},
|
||||
{"shoes", "FEET"},
|
||||
{"id", "IDCARD"},
|
||||
{"pocket1", "POCKET1"},
|
||||
{"pocket2", "POCKET2"},
|
||||
{"suitstorage", "SUITSTORAGE"},
|
||||
{ "head", "HELMET" },
|
||||
{ "eyes", "EYES" },
|
||||
{ "ears", "EARS" },
|
||||
{ "mask", "MASK" },
|
||||
{ "outerClothing", "OUTERCLOTHING" },
|
||||
{ Jumpsuit, "INNERCLOTHING" },
|
||||
{ "neck", "NECK" },
|
||||
{ "back", "BACKPACK" },
|
||||
{ "belt", "BELT" },
|
||||
{ "gloves", "HAND" },
|
||||
{ "shoes", "FEET" },
|
||||
{ "id", "IDCARD" },
|
||||
{ "pocket1", "POCKET1" },
|
||||
{ "pocket2", "POCKET2" },
|
||||
{ "suitstorage", "SUITSTORAGE" },
|
||||
//WHITE EDIT
|
||||
{"socks", "SOCKS"},
|
||||
{"underweart", "UNDERWEART"},
|
||||
{"underwearb", "UNDERWEARB"},
|
||||
{ "socks", "SOCKS" },
|
||||
{ "underweart", "UNDERWEART" },
|
||||
{ "underwearb", "UNDERWEARB" },
|
||||
// WHITE EDIT
|
||||
};
|
||||
|
||||
[Dependency] private readonly IResourceCache _cache = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -99,8 +102,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
// if that returned nothing, attempt to find generic data
|
||||
if (layers == null && !item.ClothingVisuals.TryGetValue(args.Slot, out layers))
|
||||
{
|
||||
if (!TryComp(args.Equipee, out HumanoidAppearanceComponent? humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// No generic data either. Attempt to generate defaults from the item's RSI & item-prefixes
|
||||
if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, out layers))
|
||||
if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, humanoid, out layers))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,7 +134,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
/// <remarks>
|
||||
/// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility.
|
||||
/// </remarks>
|
||||
private bool TryGetDefaultVisuals(EntityUid uid, ClothingComponent clothing, string slot, string? speciesId,
|
||||
private bool TryGetDefaultVisuals(
|
||||
EntityUid uid,
|
||||
ClothingComponent clothing,
|
||||
string slot,
|
||||
string? speciesId,
|
||||
HumanoidAppearanceComponent humanoid,
|
||||
[NotNullWhen(true)] out List<PrototypeLayerData>? layers)
|
||||
{
|
||||
layers = null;
|
||||
@@ -138,14 +151,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
else if (TryComp(uid, out SpriteComponent? sprite))
|
||||
rsi = sprite.BaseRSI;
|
||||
|
||||
if (rsi == null || rsi.Path == null)
|
||||
if (rsi?.Path == null)
|
||||
return false;
|
||||
|
||||
var correctedSlot = slot;
|
||||
TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot);
|
||||
|
||||
|
||||
|
||||
var state = $"equipped-{correctedSlot}";
|
||||
|
||||
if (clothing.EquippedPrefix != null)
|
||||
@@ -154,6 +165,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
if (clothing.EquippedState != null)
|
||||
state = $"{clothing.EquippedState}";
|
||||
|
||||
// body type specific
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(humanoid.BodyType);
|
||||
if (rsi.TryGetState($"{state}-{bodyTypeProto.Name}", out _))
|
||||
{
|
||||
state = $"{state}-{bodyTypeProto.Name}";
|
||||
}
|
||||
|
||||
// species specific
|
||||
if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _))
|
||||
{
|
||||
@@ -164,10 +182,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var layer = new PrototypeLayerData();
|
||||
layer.RsiPath = rsi.Path.ToString();
|
||||
layer.State = state;
|
||||
layers = new() { layer };
|
||||
var layer = new PrototypeLayerData
|
||||
{
|
||||
RsiPath = rsi.Path.ToString(),
|
||||
State = state
|
||||
};
|
||||
|
||||
layers = new List<PrototypeLayerData> { layer };
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -189,7 +210,7 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
&& TryComp(uid, out SpriteComponent? sprite)
|
||||
&& sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var maskLayer))
|
||||
{
|
||||
sprite.LayerSetVisible(maskLayer, false);
|
||||
sprite.LayerSetVisible(maskLayer, false);
|
||||
}
|
||||
|
||||
if (!TryComp(uid, out InventorySlotsComponent? inventorySlots))
|
||||
@@ -204,6 +225,7 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
component.RemoveLayer(layer);
|
||||
}
|
||||
|
||||
revealedLayers.Clear();
|
||||
}
|
||||
|
||||
@@ -226,12 +248,17 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
RenderEquipment(args.Equipee, uid, args.Slot, clothingComponent: component);
|
||||
}
|
||||
|
||||
private void RenderEquipment(EntityUid equipee, EntityUid equipment, string slot,
|
||||
InventoryComponent? inventory = null, SpriteComponent? sprite = null, ClothingComponent? clothingComponent = null,
|
||||
private void RenderEquipment(
|
||||
EntityUid equipee,
|
||||
EntityUid equipment,
|
||||
string slot,
|
||||
InventoryComponent? inventory = null,
|
||||
SpriteComponent? sprite = null,
|
||||
ClothingComponent? clothingComponent = null,
|
||||
InventorySlotsComponent? inventorySlots = null)
|
||||
{
|
||||
if (!Resolve(equipee, ref inventory, ref sprite, ref inventorySlots) ||
|
||||
!Resolve(equipment, ref clothingComponent, false))
|
||||
!Resolve(equipment, ref clothingComponent, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -250,11 +277,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
sprite.RemoveLayer(key);
|
||||
}
|
||||
|
||||
revealedLayers.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
revealedLayers = new();
|
||||
revealedLayers = new HashSet<string>();
|
||||
inventorySlots.VisualLayerKeys[slot] = revealedLayers;
|
||||
}
|
||||
|
||||
@@ -276,7 +304,9 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
if (!revealedLayers.Add(key))
|
||||
{
|
||||
Logger.Warning($"Duplicate key for clothing visuals: {key}. Are multiple components attempting to modify the same layer? Equipment: {ToPrettyString(equipment)}");
|
||||
Logger.Warning(
|
||||
$"Duplicate key for clothing visuals: {key}. Are multiple components attempting to modify the same layer? Equipment: {ToPrettyString(equipment)}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -315,12 +345,10 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
RaiseLocalEvent(equipment, new EquipmentVisualsUpdatedEvent(equipee, slot, revealedLayers), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets a sprite's gendered mask based on gender (obviously).
|
||||
/// </summary>
|
||||
/// <param name="sprite">Sprite to modify</param>
|
||||
/// <param name="humanoid">Humanoid, to get gender from</param>
|
||||
/// <param name="clothing">Clothing component, to get mask sprite type</param>
|
||||
private void SetGenderedMask(EntityUid uid, SpriteComponent sprite, ClothingComponent clothing)
|
||||
{
|
||||
@@ -330,7 +358,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
ClothingMask mask;
|
||||
string prefix;
|
||||
|
||||
switch (CompOrNull<HumanoidAppearanceComponent>(uid)?.Sex)
|
||||
if (!TryComp(uid, out HumanoidAppearanceComponent? humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (humanoid.Sex)
|
||||
{
|
||||
case Sex.Male:
|
||||
mask = clothing.MaleMask;
|
||||
@@ -338,7 +371,8 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
break;
|
||||
case Sex.Female:
|
||||
mask = clothing.FemaleMask;
|
||||
prefix = "female_";
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(humanoid.BodyType!);
|
||||
prefix = bodyTypeProto.Name != "body-normal" ? $"female_{bodyTypeProto.Name}_" : "female_";
|
||||
break;
|
||||
default:
|
||||
mask = clothing.UnisexMask;
|
||||
@@ -348,10 +382,11 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
|
||||
sprite.LayerSetState(layer, mask switch
|
||||
{
|
||||
ClothingMask.NoMask => $"{prefix}none",
|
||||
ClothingMask.NoMask => $"{prefix}none",
|
||||
ClothingMask.UniformTop => $"{prefix}top",
|
||||
_ => $"{prefix}full",
|
||||
_ => $"{prefix}full",
|
||||
});
|
||||
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
component.BaseLayers.Clear();
|
||||
|
||||
// add default species layers
|
||||
var speciesProto = _prototypeManager.Index(component.Species);
|
||||
var baseSprites = _prototypeManager.Index<HumanoidSpeciesBaseSpritesPrototype>(speciesProto.SpriteSet);
|
||||
foreach (var (key, id) in baseSprites.Sprites)
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(component.BodyType);
|
||||
foreach (var (key, id) in bodyTypeProto.Sprites)
|
||||
{
|
||||
oldLayers.Remove(key);
|
||||
if (!component.CustomBaseLayers.ContainsKey(key))
|
||||
@@ -108,13 +107,17 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
/// This should not be used if the entity is owned by the server. The server will otherwise
|
||||
/// override this with the appearance data it sends over.
|
||||
/// </remarks>
|
||||
public override void LoadProfile(EntityUid uid, HumanoidCharacterProfile profile, HumanoidAppearanceComponent? humanoid = null)
|
||||
public override void LoadProfile(
|
||||
EntityUid uid,
|
||||
HumanoidCharacterProfile profile,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
humanoid.BodyType = profile.BodyType;
|
||||
var customBaseLayers = new Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo>();
|
||||
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(profile.Species);
|
||||
@@ -142,15 +145,19 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
//markings.RemoveCategory(MarkingCategories.FacialHair);
|
||||
|
||||
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.Hair, out var hairAlpha,
|
||||
_prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha)
|
||||
: profile.Appearance.HairColor;
|
||||
|
||||
var hair = new Marking(profile.Appearance.HairStyleId,
|
||||
new[] { hairColor });
|
||||
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.FacialHair,
|
||||
out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha)
|
||||
: profile.Appearance.FacialHairColor;
|
||||
|
||||
var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
|
||||
new[] { facialHairColor });
|
||||
|
||||
@@ -158,6 +165,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
{
|
||||
markings.AddBack(MarkingCategories.Hair, hair);
|
||||
}
|
||||
|
||||
if (_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHair, _prototypeManager))
|
||||
{
|
||||
markings.AddBack(MarkingCategories.FacialHair, facialHair);
|
||||
@@ -172,10 +180,13 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
profile.Appearance.EyeColor,
|
||||
markings
|
||||
);
|
||||
|
||||
markings.AddBack(prototype.MarkingCategory, new Marking(marking.MarkingId, markingColors));
|
||||
}
|
||||
|
||||
markings.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||
markings.EnsureSpecies(profile.Species, profile.BodyType, profile.Appearance.SkinColor, _markingManager,
|
||||
_prototypeManager);
|
||||
|
||||
markings.EnsureSexes(profile.Sex, _markingManager);
|
||||
markings.EnsureDefault(
|
||||
profile.Appearance.SkinColor,
|
||||
@@ -190,6 +201,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
humanoid.CustomBaseLayers = customBaseLayers;
|
||||
humanoid.Sex = profile.Sex;
|
||||
humanoid.Gender = profile.Gender;
|
||||
humanoid.BodyType = profile.BodyType;
|
||||
humanoid.Age = profile.Age;
|
||||
humanoid.Species = profile.Species;
|
||||
humanoid.SkinColor = profile.Appearance.SkinColor;
|
||||
@@ -261,7 +273,9 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
spriteComp.RemoveLayer(index);
|
||||
}
|
||||
}
|
||||
private void ApplyMarking(MarkingPrototype markingPrototype,
|
||||
|
||||
private void ApplyMarking(
|
||||
MarkingPrototype markingPrototype,
|
||||
IReadOnlyList<Color>? colors,
|
||||
bool visible,
|
||||
HumanoidAppearanceComponent humanoid,
|
||||
@@ -274,7 +288,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
|
||||
visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
|
||||
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
|
||||
&& setting.AllowsMarkings;
|
||||
&& setting.AllowsMarkings;
|
||||
|
||||
for (var j = 0; j < markingPrototype.Sprites.Count; j++)
|
||||
{
|
||||
@@ -315,7 +329,12 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetSkinColor(EntityUid uid, Color skinColor, bool sync = true, bool verify = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public override void SetSkinColor(
|
||||
EntityUid uid,
|
||||
Color skinColor,
|
||||
bool sync = true,
|
||||
bool verify = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid) || humanoid.SkinColor == skinColor)
|
||||
return;
|
||||
@@ -366,7 +385,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
{
|
||||
foreach (var marking in markingList)
|
||||
{
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype) && markingPrototype.BodyPart == layer)
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype) &&
|
||||
markingPrototype.BodyPart == layer)
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, humanoid, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public sealed class HumanoidMarkingModifierBoundUserInterface : BoundUserInterfa
|
||||
return;
|
||||
}
|
||||
|
||||
_window.SetState(cast.MarkingSet, cast.Species, cast.Sex, cast.SkinColor, cast.CustomBaseLayers);
|
||||
_window.SetState(cast.MarkingSet, cast.Species, cast.Sex, cast.BodyType, cast.SkinColor, cast.CustomBaseLayers);
|
||||
}
|
||||
|
||||
private void SendMarkingSet(MarkingSet set)
|
||||
|
||||
@@ -59,10 +59,12 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
string? state = _protoMan.HasIndex<HumanoidSpeciesSpriteLayer>(modifier.Text) ? modifier.Text : null;
|
||||
OnLayerInfoModified?.Invoke(layer, new CustomBaseLayerInfo(state, modifier.Color));
|
||||
}
|
||||
|
||||
public void SetState(
|
||||
MarkingSet markings,
|
||||
string species,
|
||||
Sex sex,
|
||||
string bodyType,
|
||||
Color skinColor,
|
||||
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info
|
||||
)
|
||||
@@ -84,7 +86,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
eyesColor = eyes.Color.Value;
|
||||
}
|
||||
|
||||
MarkingPickerWidget.SetData(markings, species, sex, skinColor, eyesColor);
|
||||
MarkingPickerWidget.SetData(markings, species, sex, bodyType, skinColor, eyesColor);
|
||||
}
|
||||
|
||||
private sealed class HumanoidBaseLayerModifier : BoxContainer
|
||||
@@ -95,7 +97,9 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
private BoxContainer _infoBox;
|
||||
|
||||
public bool Enabled => _enable.Pressed;
|
||||
|
||||
public string Text => _lineEdit.Text;
|
||||
|
||||
public Color Color => _colorSliders.Color;
|
||||
|
||||
public Action? OnStateChanged;
|
||||
@@ -109,6 +113,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
MinWidth = 250,
|
||||
HorizontalExpand = true
|
||||
};
|
||||
|
||||
AddChild(labelBox);
|
||||
|
||||
labelBox.AddChild(new Label
|
||||
@@ -116,6 +121,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
HorizontalExpand = true,
|
||||
Text = layer.ToString()
|
||||
});
|
||||
|
||||
_enable = new CheckBox
|
||||
{
|
||||
Text = "Enable",
|
||||
@@ -128,6 +134,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
_enable.OnToggled += args =>
|
||||
{
|
||||
_infoBox.Visible = args.Pressed;
|
||||
@@ -135,7 +142,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
};
|
||||
|
||||
var lineEditBox = new BoxContainer();
|
||||
lineEditBox.AddChild(new Label { Text = "Prototype id: "});
|
||||
lineEditBox.AddChild(new Label { Text = "Prototype id: " });
|
||||
|
||||
// TODO: This line edit should really be an options / dropdown selector, not text.
|
||||
_lineEdit = new() { MinWidth = 200 };
|
||||
|
||||
@@ -40,6 +40,7 @@ public sealed partial class MarkingPicker : Control
|
||||
private List<MarkingCategories> _markingCategories = Enum.GetValues<MarkingCategories>().ToList();
|
||||
|
||||
private string _currentSpecies = SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||
private string _currentBodyType = SharedHumanoidAppearanceSystem.DefaultBodyType;
|
||||
private Sex _currentSex = Sex.Unsexed;
|
||||
public Color CurrentSkinColor = Color.White;
|
||||
public Color CurrentEyeColor = Color.Black;
|
||||
@@ -83,7 +84,7 @@ public sealed partial class MarkingPicker : Control
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(List<Marking> newMarkings, string species, Sex sex, Color skinColor, Color eyeColor)
|
||||
public void SetData(List<Marking> newMarkings, string species, Sex sex, string bodyType, Color skinColor, Color eyeColor)
|
||||
{
|
||||
var pointsProto = _prototypeManager
|
||||
.Index<SpeciesPrototype>(species).MarkingPoints;
|
||||
@@ -91,7 +92,7 @@ public sealed partial class MarkingPicker : Control
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
_currentMarkings.EnsureSpecies(species, bodyType, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
}
|
||||
|
||||
_currentSpecies = species;
|
||||
@@ -103,13 +104,13 @@ public sealed partial class MarkingPicker : Control
|
||||
PopulateUsed();
|
||||
}
|
||||
|
||||
public void SetData(MarkingSet set, string species, Sex sex, Color skinColor, Color eyeColor)
|
||||
public void SetData(MarkingSet set, string species, Sex sex, string bodyType, Color skinColor, Color eyeColor)
|
||||
{
|
||||
_currentMarkings = set;
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
_currentMarkings.EnsureSpecies(species, bodyType, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
}
|
||||
|
||||
_currentSpecies = species;
|
||||
@@ -234,7 +235,7 @@ public sealed partial class MarkingPicker : Control
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, _currentBodyType, null, _markingManager);
|
||||
}
|
||||
|
||||
// walk backwards through the list for visual purposes
|
||||
@@ -338,7 +339,7 @@ public sealed partial class MarkingPicker : Control
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(species);
|
||||
|
||||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
_currentMarkings.EnsureSpecies(species, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(species, _currentBodyType, null, _markingManager);
|
||||
_currentMarkings.EnsureSexes(_currentSex, _markingManager);
|
||||
|
||||
Populate(CMarkingSearch.Text);
|
||||
@@ -353,7 +354,7 @@ public sealed partial class MarkingPicker : Control
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(_currentSpecies);
|
||||
|
||||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, _currentBodyType, null, _markingManager);
|
||||
_currentMarkings.EnsureSexes(_currentSex, _markingManager);
|
||||
|
||||
Populate(CMarkingSearch.Text);
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
<Control HorizontalExpand="True"/>
|
||||
<OptionButton Name="CSpeciesButton" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
<!-- Body Type -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-body-type-label'}"/>
|
||||
<Control HorizontalExpand="True"/>
|
||||
<OptionButton Name="CBodyTypesButton" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
<!-- Age -->
|
||||
<BoxContainer HorizontalExpand="True">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-age-label'}" />
|
||||
|
||||
@@ -14,13 +14,11 @@ using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Content.Shared.Traits;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -29,10 +27,8 @@ using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
@@ -44,7 +40,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
public HighlightedContainer()
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat()
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = new Color(25, 25, 25),
|
||||
ContentMarginTopOverride = 10,
|
||||
@@ -110,6 +106,7 @@ namespace Content.Client.Preferences.UI
|
||||
private readonly List<SpeciesPrototype> _speciesList;
|
||||
private readonly List<AntagPreferenceSelector> _antagPreferences;
|
||||
private readonly List<TraitPreferenceSelector> _traitPreferences;
|
||||
private List<BodyTypePrototype> _bodyTypesList = new();
|
||||
|
||||
private SpriteView _previewSpriteView => CSpriteView;
|
||||
private Button _previewRotateLeftButton => CSpriteRotateLeft;
|
||||
@@ -177,6 +174,14 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
#endregion Sex
|
||||
|
||||
#region Body Type
|
||||
|
||||
CBodyTypesButton.OnItemSelected += OnBodyTypeSelected;
|
||||
|
||||
UpdateBodyTypes();
|
||||
|
||||
#endregion Body Type
|
||||
|
||||
#region Age
|
||||
|
||||
_ageEdit.OnTextChanged += args =>
|
||||
@@ -845,6 +850,7 @@ namespace Content.Client.Preferences.UI
|
||||
CMarkings.SetSpecies(newSpecies); // Repopulate the markings tab as well.
|
||||
UpdateSexControls(); // update sex for new species
|
||||
RebuildSpriteView(); // they might have different inv so we need a new dummy
|
||||
UpdateBodyTypes();
|
||||
IsDirty = true;
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
@@ -903,6 +909,38 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBodyTypeSelected(OptionButton.ItemSelectedEventArgs args)
|
||||
{
|
||||
args.Button.SelectId(args.Id);
|
||||
SetBodyType(_bodyTypesList[args.Id].ID);
|
||||
}
|
||||
|
||||
private void UpdateBodyTypes()
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
|
||||
CBodyTypesButton.Clear();
|
||||
var species = _prototypeManager.Index<SpeciesPrototype>(Profile.Species);
|
||||
var sex = Profile.Sex;
|
||||
_bodyTypesList = EntitySystem.Get<HumanoidAppearanceSystem>().GetValidBodyTypes(species, sex);
|
||||
|
||||
for (var i = 0; i < _bodyTypesList.Count; i++)
|
||||
{
|
||||
CBodyTypesButton.AddItem(Loc.GetString(_bodyTypesList[i].Name), i);
|
||||
}
|
||||
|
||||
// If current body type is not valid.
|
||||
if (!_bodyTypesList.Select(proto => proto.ID).Contains(Profile.BodyType))
|
||||
{
|
||||
// Then replace it with a first valid body type.
|
||||
SetBodyType(_bodyTypesList.First().ID);
|
||||
}
|
||||
|
||||
CBodyTypesButton.Select(_bodyTypesList.FindIndex(x => x.ID == Profile.BodyType));
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private bool IsDirty
|
||||
{
|
||||
get => _isDirty;
|
||||
@@ -1025,7 +1063,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
|
||||
CMarkings.SetData(Profile.Appearance.Markings, Profile.Species,
|
||||
Profile.Sex, Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
|
||||
Profile.Sex, Profile.BodyType, Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1090,13 +1128,13 @@ namespace Content.Client.Preferences.UI
|
||||
var hairMarking = Profile.Appearance.HairStyleId switch
|
||||
{
|
||||
HairStyles.DefaultHairStyle => new List<Marking>(),
|
||||
_ => new() { new(Profile.Appearance.HairStyleId, new List<Color>() { Profile.Appearance.HairColor }) },
|
||||
_ => new() { new(Profile.Appearance.HairStyleId, new List<Color> { Profile.Appearance.HairColor }) },
|
||||
};
|
||||
|
||||
var facialHairMarking = Profile.Appearance.FacialHairStyleId switch
|
||||
{
|
||||
HairStyles.DefaultFacialHairStyle => new List<Marking>(),
|
||||
_ => new() { new(Profile.Appearance.FacialHairStyleId, new List<Color>() { Profile.Appearance.FacialHairColor }) },
|
||||
_ => new() { new(Profile.Appearance.FacialHairStyleId, new List<Color> { Profile.Appearance.FacialHairColor }) },
|
||||
};
|
||||
|
||||
_hairPicker.UpdateData(
|
||||
@@ -1124,7 +1162,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, hairProto, _prototypeManager))
|
||||
{
|
||||
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
|
||||
if (_markingManager.MustMatchSkin(Profile.BodyType, HumanoidVisualLayers.Hair, out _, _prototypeManager))
|
||||
{
|
||||
hairColor = Profile.Appearance.SkinColor;
|
||||
}
|
||||
@@ -1136,7 +1174,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
if (hairColor != null)
|
||||
{
|
||||
CMarkings.HairMarking = new (Profile.Appearance.HairStyleId, new List<Color>() { hairColor.Value });
|
||||
CMarkings.HairMarking = new (Profile.Appearance.HairStyleId, new List<Color> { hairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1159,7 +1197,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, facialHairProto, _prototypeManager))
|
||||
{
|
||||
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
|
||||
if (_markingManager.MustMatchSkin(Profile.BodyType, HumanoidVisualLayers.Hair, out _, _prototypeManager))
|
||||
{
|
||||
facialHairColor = Profile.Appearance.SkinColor;
|
||||
}
|
||||
@@ -1171,7 +1209,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
if (facialHairColor != null)
|
||||
{
|
||||
CMarkings.FacialHairMarking = new (Profile.Appearance.FacialHairStyleId, new List<Color>() { facialHairColor.Value });
|
||||
CMarkings.FacialHairMarking = new (Profile.Appearance.FacialHairStyleId, new List<Color> { facialHairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1237,6 +1275,7 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
//WD-EDIT
|
||||
UpdateTTSVoicesControls();
|
||||
UpdateBodyTypes();
|
||||
//WD-EDIT
|
||||
|
||||
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
||||
@@ -1299,6 +1338,14 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
return allowedSpecies;
|
||||
}
|
||||
|
||||
private void SetBodyType(string newBodyType)
|
||||
{
|
||||
Profile = Profile?.WithBodyType(newBodyType);
|
||||
IsDirty = true;
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
|
||||
//WD EDIT END
|
||||
|
||||
private void UpdateJobPriorities()
|
||||
@@ -1337,7 +1384,7 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
Options.OnItemSelected += args => Options.Select(args.Id);
|
||||
|
||||
_requirementsLabel = new Label()
|
||||
_requirementsLabel = new Label
|
||||
{
|
||||
Text = Loc.GetString("role-timer-locked"),
|
||||
Visible = true,
|
||||
@@ -1345,7 +1392,7 @@ namespace Content.Client.Preferences.UI
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText},
|
||||
};
|
||||
|
||||
_lockStripe = new StripeBack()
|
||||
_lockStripe = new StripeBack
|
||||
{
|
||||
Visible = false,
|
||||
HorizontalExpand = true,
|
||||
@@ -1369,7 +1416,7 @@ namespace Content.Client.Preferences.UI
|
||||
Options.AddItem(Loc.GetString(text), value);
|
||||
}
|
||||
|
||||
var titleLabel = new Label()
|
||||
var titleLabel = new Label
|
||||
{
|
||||
Margin = new Thickness(5f, 0, 5f, 0),
|
||||
Text = title,
|
||||
|
||||
@@ -11,7 +11,6 @@ using Robust.Shared.Enums;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.UnitTesting;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Preferences
|
||||
@@ -49,6 +48,7 @@ namespace Content.IntegrationTests.Tests.Preferences
|
||||
21,
|
||||
Sex.Male,
|
||||
Gender.Epicene,
|
||||
"Normal",
|
||||
new HumanoidCharacterAppearance(
|
||||
"Afro",
|
||||
Color.Aqua,
|
||||
|
||||
1821
Content.Server.Database/Migrations/Postgres/20240219145443_AddBodyType.Designer.cs
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddBodyType : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "body_type",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "body_type",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -760,6 +760,11 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("BodyType")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("body_type");
|
||||
|
||||
b.Property<string>("BorgName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
|
||||
1750
Content.Server.Database/Migrations/Sqlite/20240219145431_AddBodyType.Designer.cs
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddBodyType : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "body_type",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "body_type",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,6 +711,11 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("backpack");
|
||||
|
||||
b.Property<string>("BodyType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("body_type");
|
||||
|
||||
b.Property<string>("BorgName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
|
||||
@@ -343,6 +343,7 @@ namespace Content.Server.Database
|
||||
public string Gender { get; set; } = null!;
|
||||
|
||||
//WD-EDIT
|
||||
public string BodyType { get; set; } = null!;
|
||||
public string Voice { get; set; } = null!;
|
||||
//WD-EDIT
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ namespace Content.Server.Database
|
||||
if (Enum.TryParse<Sex>(profile.Sex, true, out var sexVal))
|
||||
sex = sexVal;
|
||||
|
||||
var bodyType = profile.BodyType;
|
||||
var clothing = ClothingPreference.Jumpsuit;
|
||||
if (Enum.TryParse<ClothingPreference>(profile.Clothing, true, out var clothingVal))
|
||||
clothing = clothingVal;
|
||||
@@ -225,6 +226,7 @@ namespace Content.Server.Database
|
||||
profile.Age,
|
||||
sex,
|
||||
gender,
|
||||
bodyType,
|
||||
new HumanoidCharacterAppearance
|
||||
(
|
||||
profile.HairName,
|
||||
@@ -265,6 +267,7 @@ namespace Content.Server.Database
|
||||
profile.Age = humanoid.Age;
|
||||
profile.Sex = humanoid.Sex.ToString();
|
||||
profile.Gender = humanoid.Gender.ToString();
|
||||
profile.BodyType = humanoid.BodyType;
|
||||
profile.HairName = appearance.HairStyleId;
|
||||
profile.HairColor = appearance.HairColor.ToHex();
|
||||
profile.FacialHairName = appearance.FacialHairStyleId;
|
||||
|
||||
@@ -29,7 +29,7 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
{
|
||||
Text = "Modify markings",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Customization/reptilian_parts.rsi"), "tail_smooth"),
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Mobs/Customization/reptilian_parts.rsi"), "tail_smooth"),
|
||||
Act = () =>
|
||||
{
|
||||
_uiSystem.TryOpen(uid, HumanoidMarkingModifierKey.Key, actor.PlayerSession);
|
||||
@@ -37,6 +37,7 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
uid,
|
||||
HumanoidMarkingModifierKey.Key,
|
||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||
component.BodyType,
|
||||
component.Sex,
|
||||
component.SkinColor,
|
||||
component.CustomBaseLayers
|
||||
@@ -45,7 +46,9 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
});
|
||||
}
|
||||
|
||||
private void OnBaseLayersSet(EntityUid uid, HumanoidAppearanceComponent component,
|
||||
private void OnBaseLayersSet(
|
||||
EntityUid uid,
|
||||
HumanoidAppearanceComponent component,
|
||||
HumanoidMarkingModifierBaseLayersSetMessage message)
|
||||
{
|
||||
if (message.Session is not { } player
|
||||
@@ -63,7 +66,7 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
component.CustomBaseLayers[message.Layer] = message.Info.Value;
|
||||
}
|
||||
|
||||
Dirty(component);
|
||||
Dirty(uid, component);
|
||||
|
||||
if (message.ResendState)
|
||||
{
|
||||
@@ -71,14 +74,17 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
uid,
|
||||
HumanoidMarkingModifierKey.Key,
|
||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||
component.Sex,
|
||||
component.SkinColor,
|
||||
component.CustomBaseLayers
|
||||
));
|
||||
component.BodyType,
|
||||
component.Sex,
|
||||
component.SkinColor,
|
||||
component.CustomBaseLayers
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMarkingsSet(EntityUid uid, HumanoidAppearanceComponent component,
|
||||
private void OnMarkingsSet(
|
||||
EntityUid uid,
|
||||
HumanoidAppearanceComponent component,
|
||||
HumanoidMarkingModifierMarkingSetMessage message)
|
||||
{
|
||||
if (message.Session is not { } player
|
||||
@@ -88,7 +94,7 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
}
|
||||
|
||||
component.MarkingSet = message.MarkingSet;
|
||||
Dirty(component);
|
||||
Dirty(uid, component);
|
||||
|
||||
if (message.ResendState)
|
||||
{
|
||||
@@ -96,11 +102,11 @@ public sealed partial class HumanoidAppearanceSystem
|
||||
uid,
|
||||
HumanoidMarkingModifierKey.Key,
|
||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||
component.Sex,
|
||||
component.SkinColor,
|
||||
component.CustomBaseLayers
|
||||
));
|
||||
component.BodyType,
|
||||
component.Sex,
|
||||
component.SkinColor,
|
||||
component.CustomBaseLayers
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
@@ -27,11 +26,12 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
|
||||
private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
|
||||
{
|
||||
var identity = Identity.Entity(component.Owner, EntityManager);
|
||||
var identity = Identity.Entity(uid, EntityManager);
|
||||
var species = GetSpeciesRepresentation(component.Species).ToLower();
|
||||
var age = GetAgeRepresentation(component.Species, component.Age);
|
||||
|
||||
args.PushText(Loc.GetString("humanoid-appearance-component-examine", ("user", identity), ("age", age), ("species", species)));
|
||||
args.PushText(Loc.GetString("humanoid-appearance-component-examine", ("user", identity), ("age", age),
|
||||
("species", species)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -40,7 +40,10 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="uid">The mob's entity UID.</param>
|
||||
/// <param name="profile">The character profile to load.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void LoadProfile(EntityUid uid, HumanoidCharacterProfile profile, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void LoadProfile(
|
||||
EntityUid uid,
|
||||
HumanoidCharacterProfile profile,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
{
|
||||
@@ -51,6 +54,8 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
SetSex(uid, profile.Sex, false, humanoid);
|
||||
humanoid.EyeColor = profile.Appearance.EyeColor;
|
||||
|
||||
SetBodyType(uid, profile.BodyType, false, humanoid);
|
||||
|
||||
SetSkinColor(uid, profile.Appearance.SkinColor, false);
|
||||
|
||||
humanoid.MarkingSet.Clear();
|
||||
@@ -74,10 +79,15 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
|
||||
// Hair/facial hair - this may eventually be deprecated.
|
||||
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha) : profile.Appearance.HairColor;
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha) : profile.Appearance.FacialHairColor;
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.Hair, out var hairAlpha,
|
||||
_prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha)
|
||||
: profile.Appearance.HairColor;
|
||||
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.FacialHair,
|
||||
out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha)
|
||||
: profile.Appearance.FacialHairColor;
|
||||
|
||||
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
|
||||
_markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _prototypeManager))
|
||||
@@ -86,12 +96,14 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
}
|
||||
|
||||
if (_markingManager.Markings.TryGetValue(profile.Appearance.FacialHairStyleId, out var facialHairPrototype) &&
|
||||
_markingManager.CanBeApplied(profile.Species,profile.Sex, facialHairPrototype, _prototypeManager))
|
||||
_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHairPrototype, _prototypeManager))
|
||||
{
|
||||
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
|
||||
}
|
||||
|
||||
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.BodyType, profile.Appearance.SkinColor,
|
||||
_markingManager,
|
||||
_prototypeManager);
|
||||
|
||||
// Finally adding marking with forced colors
|
||||
foreach (var (marking, prototype) in markingFColored)
|
||||
@@ -102,6 +114,7 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
profile.Appearance.EyeColor,
|
||||
humanoid.MarkingSet
|
||||
);
|
||||
|
||||
AddMarking(uid, marking.MarkingId, markingColors, false);
|
||||
}
|
||||
|
||||
@@ -128,7 +141,10 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="target">Target entity to apply the source entity's appearance to.</param>
|
||||
/// <param name="sourceHumanoid">Source entity's humanoid component.</param>
|
||||
/// <param name="targetHumanoid">Target entity's humanoid component.</param>
|
||||
public void CloneAppearance(EntityUid source, EntityUid target, HumanoidAppearanceComponent? sourceHumanoid = null,
|
||||
public void CloneAppearance(
|
||||
EntityUid source,
|
||||
EntityUid target,
|
||||
HumanoidAppearanceComponent? sourceHumanoid = null,
|
||||
HumanoidAppearanceComponent? targetHumanoid = null)
|
||||
{
|
||||
if (!Resolve(source, ref sourceHumanoid) || !Resolve(target, ref targetHumanoid))
|
||||
@@ -143,6 +159,8 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
SetSex(target, sourceHumanoid.Sex, false, targetHumanoid);
|
||||
targetHumanoid.CustomBaseLayers = new(sourceHumanoid.CustomBaseLayers);
|
||||
targetHumanoid.MarkingSet = new(sourceHumanoid.MarkingSet);
|
||||
targetHumanoid.BodyType = sourceHumanoid.BodyType;
|
||||
SetTTSVoice(target, sourceHumanoid.Voice, targetHumanoid);
|
||||
|
||||
targetHumanoid.Gender = sourceHumanoid.Gender;
|
||||
if (TryComp<GrammarComponent>(target, out var grammar))
|
||||
@@ -153,6 +171,32 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
Dirty(targetHumanoid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a humanoid mob's body yupe. This will change their base sprites.
|
||||
/// </summary>
|
||||
/// <param name="uid">The humanoid mob's UID.</param>
|
||||
/// <param name="bodyType">The body type to set the mob to. Will return if the body type prototype was invalid.</param>
|
||||
/// <param name="sync">Whether to immediately synchronize this to the humanoid mob, or not.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetBodyType(
|
||||
EntityUid uid,
|
||||
string bodyType,
|
||||
bool sync = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid) || !_prototypeManager.TryIndex<BodyTypePrototype>(bodyType, out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
humanoid.BodyType = bodyType;
|
||||
|
||||
if (sync)
|
||||
{
|
||||
Dirty(uid, humanoid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a marking to this humanoid.
|
||||
/// </summary>
|
||||
@@ -162,7 +206,13 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="sync">Whether to immediately sync this marking or not</param>
|
||||
/// <param name="forced">If this marking was forced (ignores marking points)</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void AddMarking(EntityUid uid, string marking, Color? color = null, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void AddMarking(
|
||||
EntityUid uid,
|
||||
string marking,
|
||||
Color? color = null,
|
||||
bool sync = true,
|
||||
bool forced = false,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
@@ -195,7 +245,13 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="sync">Whether to immediately sync this marking or not</param>
|
||||
/// <param name="forced">If this marking was forced (ignores marking points)</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void AddMarking(EntityUid uid, string marking, IReadOnlyList<Color> colors, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void AddMarking(
|
||||
EntityUid uid,
|
||||
string marking,
|
||||
IReadOnlyList<Color> colors,
|
||||
bool sync = true,
|
||||
bool forced = false,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
@@ -218,7 +274,11 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="marking">The marking to try and remove.</param>
|
||||
/// <param name="sync">Whether to immediately sync this to the humanoid</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void RemoveMarking(EntityUid uid, string marking, bool sync = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void RemoveMarking(
|
||||
EntityUid uid,
|
||||
string marking,
|
||||
bool sync = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
@@ -239,7 +299,11 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="category">Category of the marking</param>
|
||||
/// <param name="index">Index of the marking</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void RemoveMarking(EntityUid uid, MarkingCategories category, int index, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void RemoveMarking(
|
||||
EntityUid uid,
|
||||
MarkingCategories category,
|
||||
int index,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (index < 0
|
||||
|| !Resolve(uid, ref humanoid)
|
||||
@@ -261,7 +325,12 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="index">Index of the marking</param>
|
||||
/// <param name="markingId">The marking ID to use</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetMarkingId(EntityUid uid, MarkingCategories category, int index, string markingId, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void SetMarkingId(
|
||||
EntityUid uid,
|
||||
MarkingCategories category,
|
||||
int index,
|
||||
string markingId,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (index < 0
|
||||
|| !_markingManager.MarkingsByCategory(category).TryGetValue(markingId, out var markingPrototype)
|
||||
@@ -290,7 +359,11 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// <param name="index">Index of the marking</param>
|
||||
/// <param name="colors">The marking colors to use</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetMarkingColor(EntityUid uid, MarkingCategories category, int index, List<Color> colors,
|
||||
public void SetMarkingColor(
|
||||
EntityUid uid,
|
||||
MarkingCategories category,
|
||||
int index,
|
||||
List<Color> colors,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (index < 0
|
||||
@@ -314,37 +387,24 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
/// </summary>
|
||||
public string GetSpeciesRepresentation(string speciesId)
|
||||
{
|
||||
if (_prototypeManager.TryIndex<SpeciesPrototype>(speciesId, out var species))
|
||||
{
|
||||
return Loc.GetString(species.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Loc.GetString("humanoid-appearance-component-unknown-species");
|
||||
}
|
||||
return Loc.GetString(_prototypeManager.TryIndex<SpeciesPrototype>(speciesId, out var species)
|
||||
? species.Name
|
||||
: "humanoid-appearance-component-unknown-species");
|
||||
}
|
||||
|
||||
public string GetAgeRepresentation(string species, int age)
|
||||
{
|
||||
_prototypeManager.TryIndex<SpeciesPrototype>(species, out var speciesPrototype);
|
||||
|
||||
if (speciesPrototype == null)
|
||||
if (speciesPrototype != null)
|
||||
{
|
||||
Logger.Error("Tried to get age representation of species that couldn't be indexed: " + species);
|
||||
return Loc.GetString("identity-age-young");
|
||||
return age < speciesPrototype.YoungAge
|
||||
? Loc.GetString("identity-age-young")
|
||||
: Loc.GetString(age < speciesPrototype.OldAge ? "identity-age-middle-aged" : "identity-age-old");
|
||||
}
|
||||
|
||||
if (age < speciesPrototype.YoungAge)
|
||||
{
|
||||
return Loc.GetString("identity-age-young");
|
||||
}
|
||||
|
||||
if (age < speciesPrototype.OldAge)
|
||||
{
|
||||
return Loc.GetString("identity-age-middle-aged");
|
||||
}
|
||||
|
||||
return Loc.GetString("identity-age-old");
|
||||
Logger.Error("Tried to get age representation of species that couldn't be indexed: " + species);
|
||||
return Loc.GetString("identity-age-young");
|
||||
}
|
||||
|
||||
private void EnsureDefaultMarkings(EntityUid uid, HumanoidAppearanceComponent? humanoid)
|
||||
@@ -353,6 +413,7 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
humanoid.MarkingSet.EnsureDefault(humanoid.SkinColor, humanoid.EyeColor, _markingManager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Content.Server.Database;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server._White.Sponsors;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
@@ -16,7 +17,6 @@ using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
|
||||
namespace Content.Server.Preferences.Managers
|
||||
{
|
||||
/// <summary>
|
||||
@@ -90,6 +90,7 @@ namespace Content.Server.Preferences.Managers
|
||||
{
|
||||
Logger.WarningS("prefs",
|
||||
$"User {userId} sent a {nameof(MsgUpdateCharacter)} with a null profile in slot {slot}.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,7 +108,9 @@ namespace Content.Server.Preferences.Managers
|
||||
var curPrefs = prefsData.Prefs!;
|
||||
|
||||
// WD-EDIT
|
||||
var allowedMarkings = _sponsors.TryGetInfo(message.MsgChannel.UserId, out var sponsor) ? sponsor.AllowedMarkings : new string[]{};
|
||||
var allowedMarkings = _sponsors.TryGetInfo(message.MsgChannel.UserId, out var sponsor)
|
||||
? sponsor.AllowedMarkings
|
||||
: new string[] { };
|
||||
|
||||
bool isAdminSpecie = false;
|
||||
if (_playerManager.TryGetSessionById(message.MsgChannel.UserId, out var session))
|
||||
@@ -168,7 +171,8 @@ namespace Content.Server.Preferences.Managers
|
||||
var arr = new Dictionary<int, ICharacterProfile>(curPrefs.Characters);
|
||||
arr.Remove(slot);
|
||||
|
||||
prefsData.Prefs = new PlayerPreferences(arr, nextSlot ?? curPrefs.SelectedCharacterIndex, curPrefs.AdminOOCColor);
|
||||
prefsData.Prefs =
|
||||
new PlayerPreferences(arr, nextSlot ?? curPrefs.SelectedCharacterIndex, curPrefs.AdminOOCColor);
|
||||
|
||||
if (ShouldStorePrefs(message.MsgChannel.AuthType))
|
||||
{
|
||||
@@ -193,7 +197,7 @@ namespace Content.Server.Preferences.Managers
|
||||
{
|
||||
PrefsLoaded = true,
|
||||
Prefs = new PlayerPreferences(
|
||||
new[] {new KeyValuePair<int, ICharacterProfile>(0, HumanoidCharacterProfile.Random())},
|
||||
new[] { new KeyValuePair<int, ICharacterProfile>(0, HumanoidCharacterProfile.Random()) },
|
||||
0, Color.Transparent)
|
||||
};
|
||||
|
||||
@@ -214,8 +218,13 @@ namespace Content.Server.Preferences.Managers
|
||||
// WD-EDIT
|
||||
foreach (var (_, profile) in prefs.Characters)
|
||||
{
|
||||
var allowedMarkings = _sponsors.TryGetInfo(session.UserId, out var sponsor) ? sponsor.AllowedMarkings : new string[]{};
|
||||
bool isAdminSpecie = _adminManager.HasAdminFlag(session, Shared.Administration.AdminFlags.AdminSpecies);
|
||||
var allowedMarkings = _sponsors.TryGetInfo(session.UserId, out var sponsor)
|
||||
? sponsor.AllowedMarkings
|
||||
: new string[] { };
|
||||
|
||||
bool isAdminSpecie =
|
||||
_adminManager.HasAdminFlag(session, Shared.Administration.AdminFlags.AdminSpecies);
|
||||
|
||||
profile.EnsureValid(allowedMarkings, isAdminSpecie);
|
||||
}
|
||||
// WD-EDIT
|
||||
@@ -229,6 +238,7 @@ namespace Content.Server.Preferences.Managers
|
||||
{
|
||||
MaxCharacterSlots = GetMaxUserCharacterSlots(session.UserId)
|
||||
};
|
||||
|
||||
_netManager.ServerSendMessage(msg, session.Channel);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +267,8 @@ namespace Content.Server.Preferences.Managers
|
||||
/// <param name="userId">User Id to get preferences for</param>
|
||||
/// <param name="playerPreferences">The user preferences if true, otherwise null</param>
|
||||
/// <returns>If preferences are not null</returns>
|
||||
public bool TryGetCachedPreferences(NetUserId userId,
|
||||
public bool TryGetCachedPreferences(
|
||||
NetUserId userId,
|
||||
[NotNullWhen(true)] out PlayerPreferences? playerPreferences)
|
||||
{
|
||||
if (_cachedPlayerPrefs.TryGetValue(userId, out var prefs))
|
||||
@@ -309,21 +320,27 @@ namespace Content.Server.Preferences.Managers
|
||||
case HumanoidCharacterProfile hp:
|
||||
{
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
var selectedSpecies = HumanoidAppearanceSystem.DefaultSpecies;
|
||||
|
||||
if (prototypeManager.TryIndex<SpeciesPrototype>(hp.Species, out var species) && species.RoundStart)
|
||||
if (!prototypeManager.TryIndex<SpeciesPrototype>(hp.Species, out var selectedSpecies) ||
|
||||
selectedSpecies.RoundStart)
|
||||
{
|
||||
selectedSpecies = hp.Species;
|
||||
selectedSpecies = prototypeManager.Index<SpeciesPrototype>(hp.Species);
|
||||
}
|
||||
|
||||
if (!prototypeManager.TryIndex<BodyTypePrototype>(hp.BodyType, out var selectedBodyType) ||
|
||||
!SharedHumanoidAppearanceSystem.IsBodyTypeValid(selectedBodyType, selectedSpecies, hp.Sex))
|
||||
{
|
||||
selectedBodyType = prototypeManager.Index<BodyTypePrototype>(
|
||||
SharedHumanoidAppearanceSystem.DefaultBodyType);
|
||||
}
|
||||
|
||||
newProf = hp
|
||||
.WithJobPriorities(
|
||||
hp.JobPriorities.Where(job =>
|
||||
_protos.HasIndex<JobPrototype>(job.Key)))
|
||||
.WithAntagPreferences(
|
||||
hp.AntagPreferences.Where(antag =>
|
||||
_protos.HasIndex<AntagPrototype>(antag)))
|
||||
.WithSpecies(selectedSpecies);
|
||||
.WithJobPriorities(hp.JobPriorities.Where(job => _protos.HasIndex<JobPrototype>(job.Key)))
|
||||
.WithAntagPreferences(hp.AntagPreferences.Where(antag =>
|
||||
_protos.HasIndex<AntagPrototype>(antag)))
|
||||
.WithSpecies(selectedSpecies.ID)
|
||||
.WithBodyType(selectedBodyType.ID);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -70,10 +70,16 @@ public sealed partial class HumanoidAppearanceComponent : Component
|
||||
[DataField, AutoNetworkedField]
|
||||
public Sex Sex = Sex.Male;
|
||||
|
||||
/// <summary>
|
||||
/// Current body type.
|
||||
/// </summary>
|
||||
[DataField("bodyType", customTypeSerializer: typeof(PrototypeIdSerializer<BodyTypePrototype>)), AutoNetworkedField]
|
||||
public string BodyType = SharedHumanoidAppearanceSystem.DefaultBodyType;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public Color EyeColor = Color.Brown;
|
||||
|
||||
[DataField("voice", customTypeSerializer: typeof(PrototypeIdSerializer<TTSVoicePrototype>))]
|
||||
[DataField("voice", customTypeSerializer: typeof(PrototypeIdSerializer<TTSVoicePrototype>)), AutoNetworkedField]
|
||||
public string Voice { get; set; } = SharedHumanoidAppearanceSystem.DefaultVoice;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace Content.Shared.Humanoid
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance
|
||||
{
|
||||
public HumanoidCharacterAppearance(string hairStyleId,
|
||||
public HumanoidCharacterAppearance(
|
||||
string hairStyleId,
|
||||
Color hairColor,
|
||||
string facialHairStyleId,
|
||||
Color facialHairColor,
|
||||
@@ -91,20 +92,27 @@ namespace Content.Shared.Humanoid
|
||||
Color.Black,
|
||||
Color.Black,
|
||||
Humanoid.SkinColor.ValidHumanSkinTone,
|
||||
new ()
|
||||
new List<Marking>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static string DefaultWithBodyType(string species)
|
||||
{
|
||||
var speciesPrototype = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species);
|
||||
|
||||
return speciesPrototype.BodyTypes.First();
|
||||
}
|
||||
|
||||
public static HumanoidCharacterAppearance DefaultWithSpecies(string species)
|
||||
{
|
||||
var speciesPrototype = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species);
|
||||
var skinColor = speciesPrototype.SkinColoration switch
|
||||
{
|
||||
HumanoidSkinColor.HumanToned => Humanoid.SkinColor.HumanSkinTone(speciesPrototype.DefaultHumanSkinTone),
|
||||
HumanoidSkinColor.Hues => speciesPrototype.DefaultSkinTone,
|
||||
HumanoidSkinColor.Hues => speciesPrototype.DefaultSkinTone,
|
||||
HumanoidSkinColor.TintedHues => Humanoid.SkinColor.TintedHues(speciesPrototype.DefaultSkinTone),
|
||||
_ => Humanoid.SkinColor.ValidHumanSkinTone
|
||||
_ => Humanoid.SkinColor.ValidHumanSkinTone
|
||||
};
|
||||
|
||||
return new(
|
||||
@@ -114,7 +122,7 @@ namespace Content.Shared.Humanoid
|
||||
Color.Black,
|
||||
Color.Black,
|
||||
skinColor,
|
||||
new ()
|
||||
new()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -132,7 +140,8 @@ namespace Content.Shared.Humanoid
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var markingManager = IoCManager.Resolve<MarkingManager>();
|
||||
var hairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.Hair, species).Keys.ToList();
|
||||
var facialHairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.FacialHair, species).Keys.ToList();
|
||||
var facialHairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.FacialHair, species)
|
||||
.Keys.ToList();
|
||||
|
||||
var newHairStyle = hairStyles.Count > 0
|
||||
? random.Pick(hairStyles)
|
||||
@@ -175,7 +184,8 @@ namespace Content.Shared.Humanoid
|
||||
newSkinColor = Humanoid.SkinColor.ValidTintedHuesSkinTone(newSkinColor);
|
||||
}
|
||||
|
||||
return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor, newEyeColor, newSkinColor, new ());
|
||||
return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor,
|
||||
newEyeColor, newSkinColor, new());
|
||||
|
||||
float RandomizeColor(float channel)
|
||||
{
|
||||
@@ -188,7 +198,11 @@ namespace Content.Shared.Humanoid
|
||||
return new(color.RByte, color.GByte, color.BByte);
|
||||
}
|
||||
|
||||
public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, string[] sponsorMarkings) //WD-EDIT
|
||||
public static HumanoidCharacterAppearance EnsureValid(
|
||||
HumanoidCharacterAppearance appearance,
|
||||
string species,
|
||||
string bodyType,
|
||||
string[] sponsorMarkings) //WD-EDIT
|
||||
{
|
||||
var hairStyleId = appearance.HairStyleId;
|
||||
var facialHairStyleId = appearance.FacialHairStyleId;
|
||||
@@ -250,7 +264,7 @@ namespace Content.Shared.Humanoid
|
||||
skinColor = Humanoid.SkinColor.ValidSkinTone(speciesProto.SkinColoration, skinColor);
|
||||
}
|
||||
|
||||
markingSet.EnsureSpecies(species, skinColor, markingManager);
|
||||
markingSet.EnsureSpecies(species, bodyType, skinColor, markingManager);
|
||||
|
||||
// WD-EDIT
|
||||
markingSet.FilterSponsor(sponsorMarkings, markingManager);
|
||||
@@ -270,19 +284,23 @@ namespace Content.Shared.Humanoid
|
||||
{
|
||||
if (maybeOther is not HumanoidCharacterAppearance other)
|
||||
return false;
|
||||
|
||||
if (HairStyleId != other.HairStyleId)
|
||||
return false;
|
||||
|
||||
if (!HairColor.Equals(other.HairColor))
|
||||
return false;
|
||||
|
||||
if (FacialHairStyleId != other.FacialHairStyleId)
|
||||
return false;
|
||||
|
||||
if (!FacialHairColor.Equals(other.FacialHairColor))
|
||||
return false;
|
||||
|
||||
if (!EyeColor.Equals(other.EyeColor))
|
||||
return false;
|
||||
if (!SkinColor.Equals(other.SkinColor))
|
||||
return false;
|
||||
return Markings.SequenceEqual(other.Markings);
|
||||
|
||||
return SkinColor.Equals(other.SkinColor) && Markings.SequenceEqual(other.Markings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Humanoid
|
||||
{
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
|
||||
namespace Content.Shared.Humanoid
|
||||
@@ -10,14 +9,14 @@ namespace Content.Shared.Humanoid
|
||||
return layer switch
|
||||
{
|
||||
HumanoidVisualLayers.Chest => true,
|
||||
HumanoidVisualLayers.Head => true,
|
||||
_ => false
|
||||
HumanoidVisualLayers.Head => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetSexMorph(HumanoidVisualLayers layer, Sex sex, string id)
|
||||
{
|
||||
if (!HasSexMorph(layer) || sex == Sex.Unsexed)
|
||||
if (!HasSexMorph(layer) || sex == Sex.Unsexed || sex == Sex.Male)
|
||||
return id;
|
||||
|
||||
return $"{id}{sex}";
|
||||
@@ -42,26 +41,32 @@ namespace Content.Shared.Humanoid
|
||||
yield return HumanoidVisualLayers.Hair;
|
||||
yield return HumanoidVisualLayers.FacialHair;
|
||||
yield return HumanoidVisualLayers.Snout;
|
||||
|
||||
break;
|
||||
case HumanoidVisualLayers.LArm:
|
||||
yield return HumanoidVisualLayers.LArm;
|
||||
yield return HumanoidVisualLayers.LHand;
|
||||
|
||||
break;
|
||||
case HumanoidVisualLayers.RArm:
|
||||
yield return HumanoidVisualLayers.RArm;
|
||||
yield return HumanoidVisualLayers.RHand;
|
||||
|
||||
break;
|
||||
case HumanoidVisualLayers.LLeg:
|
||||
yield return HumanoidVisualLayers.LLeg;
|
||||
yield return HumanoidVisualLayers.LFoot;
|
||||
|
||||
break;
|
||||
case HumanoidVisualLayers.RLeg:
|
||||
yield return HumanoidVisualLayers.RLeg;
|
||||
yield return HumanoidVisualLayers.RFoot;
|
||||
|
||||
break;
|
||||
case HumanoidVisualLayers.Chest:
|
||||
yield return HumanoidVisualLayers.Chest;
|
||||
yield return HumanoidVisualLayers.Tail;
|
||||
|
||||
break;
|
||||
default:
|
||||
yield break;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Frozen;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -11,7 +10,10 @@ namespace Content.Shared.Humanoid.Markings
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private readonly List<MarkingPrototype> _index = new();
|
||||
public FrozenDictionary<MarkingCategories, FrozenDictionary<string, MarkingPrototype>> CategorizedMarkings = default!;
|
||||
|
||||
public FrozenDictionary<MarkingCategories, FrozenDictionary<string, MarkingPrototype>> CategorizedMarkings =
|
||||
default!;
|
||||
|
||||
public FrozenDictionary<string, MarkingPrototype> Markings = default!;
|
||||
|
||||
public void Initialize()
|
||||
@@ -27,7 +29,7 @@ namespace Content.Shared.Humanoid.Markings
|
||||
|
||||
foreach (var category in Enum.GetValues<MarkingCategories>())
|
||||
{
|
||||
markingDict.Add(category, new());
|
||||
markingDict.Add(category, new Dictionary<string, MarkingPrototype>());
|
||||
}
|
||||
|
||||
foreach (var prototype in _prototypeManager.EnumeratePrototypes<MarkingPrototype>())
|
||||
@@ -58,11 +60,14 @@ namespace Content.Shared.Humanoid.Markings
|
||||
/// Please make a pull request if you find a use case for that behavior.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSpecies(MarkingCategories category,
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSpecies(
|
||||
MarkingCategories category,
|
||||
string species)
|
||||
{
|
||||
var speciesProto = _prototypeManager.Index<SpeciesPrototype>(species);
|
||||
var onlyWhitelisted = _prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
var onlyWhitelisted = _prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints)
|
||||
.OnlyWhitelisted;
|
||||
|
||||
var res = new Dictionary<string, MarkingPrototype>();
|
||||
|
||||
foreach (var (key, marking) in MarkingsByCategory(category))
|
||||
@@ -76,6 +81,7 @@ namespace Content.Shared.Humanoid.Markings
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
res.Add(key, marking);
|
||||
}
|
||||
|
||||
@@ -92,7 +98,8 @@ namespace Content.Shared.Humanoid.Markings
|
||||
/// Please make a pull request if you find a use case for that behavior.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSex(MarkingCategories category,
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSex(
|
||||
MarkingCategories category,
|
||||
Sex sex)
|
||||
{
|
||||
var res = new Dictionary<string, MarkingPrototype>();
|
||||
@@ -121,11 +128,15 @@ namespace Content.Shared.Humanoid.Markings
|
||||
/// Please make a pull request if you find a use case for that behavior.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSpeciesAndSex(MarkingCategories category,
|
||||
string species, Sex sex)
|
||||
public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSpeciesAndSex(
|
||||
MarkingCategories category,
|
||||
string species,
|
||||
Sex sex)
|
||||
{
|
||||
var speciesProto = _prototypeManager.Index<SpeciesPrototype>(species);
|
||||
var onlyWhitelisted = _prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
var onlyWhitelisted = _prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints)
|
||||
.OnlyWhitelisted;
|
||||
|
||||
var res = new Dictionary<string, MarkingPrototype>();
|
||||
|
||||
foreach (var (key, marking) in MarkingsByCategory(category))
|
||||
@@ -178,12 +189,7 @@ namespace Content.Shared.Humanoid.Markings
|
||||
return false;
|
||||
}
|
||||
|
||||
if (marking.MarkingColors.Count != proto.Sprites.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return marking.MarkingColors.Count == proto.Sprites.Count;
|
||||
}
|
||||
|
||||
private void OnPrototypeReload(PrototypesReloadedEventArgs args)
|
||||
@@ -197,7 +203,8 @@ namespace Content.Shared.Humanoid.Markings
|
||||
IoCManager.Resolve(ref prototypeManager);
|
||||
|
||||
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints)
|
||||
.OnlyWhitelisted;
|
||||
|
||||
if (!TryGetMarking(marking, out var prototype))
|
||||
{
|
||||
@@ -223,12 +230,17 @@ namespace Content.Shared.Humanoid.Markings
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanBeApplied(string species, Sex sex, MarkingPrototype prototype, IPrototypeManager? prototypeManager = null)
|
||||
public bool CanBeApplied(
|
||||
string species,
|
||||
Sex sex,
|
||||
MarkingPrototype prototype,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref prototypeManager);
|
||||
|
||||
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints)
|
||||
.OnlyWhitelisted;
|
||||
|
||||
if (onlyWhitelisted && prototype.SpeciesRestrictions == null)
|
||||
{
|
||||
@@ -249,16 +261,19 @@ namespace Content.Shared.Humanoid.Markings
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool MustMatchSkin(string species, HumanoidVisualLayers layer, out float alpha, IPrototypeManager? prototypeManager = null)
|
||||
public bool MustMatchSkin(
|
||||
string speciesBodyType,
|
||||
HumanoidVisualLayers layer,
|
||||
out float alpha,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref prototypeManager);
|
||||
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||
// var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||
if (
|
||||
!prototypeManager.TryIndex(speciesProto.SpriteSet, out HumanoidSpeciesBaseSpritesPrototype? baseSprites) ||
|
||||
!prototypeManager.TryIndex(speciesBodyType, out BodyTypePrototype? baseSprites) ||
|
||||
!baseSprites.Sprites.TryGetValue(layer, out var spriteName) ||
|
||||
!prototypeManager.TryIndex(spriteName, out HumanoidSpeciesSpriteLayer? sprite) ||
|
||||
sprite == null ||
|
||||
!sprite.MarkingsMatchSkin
|
||||
sprite is not { MarkingsMatchSkin: true }
|
||||
)
|
||||
{
|
||||
alpha = 1f;
|
||||
|
||||
@@ -51,7 +51,8 @@ public sealed partial class MarkingSet
|
||||
public Dictionary<MarkingCategories, MarkingPoints> Points = new();
|
||||
|
||||
public MarkingSet()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a MarkingSet using a list of markings, and a points
|
||||
@@ -61,7 +62,11 @@ public sealed partial class MarkingSet
|
||||
/// </summary>
|
||||
/// <param name="markings">The lists of markings to use.</param>
|
||||
/// <param name="pointsPrototype">The ID of the points dictionary prototype.</param>
|
||||
public MarkingSet(List<Marking> markings, string pointsPrototype, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||
public MarkingSet(
|
||||
List<Marking> markings,
|
||||
string pointsPrototype,
|
||||
MarkingManager? markingManager = null,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref markingManager, ref prototypeManager);
|
||||
|
||||
@@ -108,7 +113,10 @@ public sealed partial class MarkingSet
|
||||
/// Construct a MarkingSet only with a points dictionary.
|
||||
/// </summary>
|
||||
/// <param name="pointsPrototype">The ID of the points dictionary prototype.</param>
|
||||
public MarkingSet(string pointsPrototype, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||
public MarkingSet(
|
||||
string pointsPrototype,
|
||||
MarkingManager? markingManager = null,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref markingManager, ref prototypeManager);
|
||||
|
||||
@@ -141,17 +149,24 @@ public sealed partial class MarkingSet
|
||||
/// Filters and colors markings based on species and it's restrictions in the marking's prototype from this marking set.
|
||||
/// </summary>
|
||||
/// <param name="species">The species to filter.</param>
|
||||
/// <param name="bodyType">Body type.</param>
|
||||
/// <param name="skinColor">The skin color for recoloring (i.e. slimes). Use null if you want only filter markings</param>
|
||||
/// <param name="markingManager">Marking manager.</param>
|
||||
/// <param name="prototypeManager">Prototype manager.</param>
|
||||
public void EnsureSpecies(string species, Color? skinColor, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||
public void EnsureSpecies(
|
||||
string species,
|
||||
string bodyType,
|
||||
Color? skinColor,
|
||||
MarkingManager? markingManager = null,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref markingManager);
|
||||
IoCManager.Resolve(ref prototypeManager);
|
||||
|
||||
var toRemove = new List<(MarkingCategories category, string id)>();
|
||||
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
var onlyWhitelisted =
|
||||
prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||
|
||||
foreach (var (category, list) in Markings)
|
||||
{
|
||||
@@ -182,17 +197,17 @@ public sealed partial class MarkingSet
|
||||
}
|
||||
|
||||
// Re-color left markings them into skin color if needed (i.e. for slimes)
|
||||
if (skinColor != null)
|
||||
if (skinColor == null)
|
||||
return;
|
||||
|
||||
foreach (var (_, list) in Markings)
|
||||
{
|
||||
foreach (var (category, list) in Markings)
|
||||
foreach (var marking in list)
|
||||
{
|
||||
foreach (var marking in list)
|
||||
if (markingManager.TryGetMarking(marking, out var prototype) &&
|
||||
markingManager.MustMatchSkin(bodyType, prototype.BodyPart, out var alpha, prototypeManager))
|
||||
{
|
||||
if (markingManager.TryGetMarking(marking, out var prototype) &&
|
||||
markingManager.MustMatchSkin(species, prototype.BodyPart, out var alpha, prototypeManager))
|
||||
{
|
||||
marking.SetColor(skinColor.Value.WithAlpha(alpha));
|
||||
}
|
||||
marking.SetColor(skinColor.Value.WithAlpha(alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,7 +280,10 @@ public sealed partial class MarkingSet
|
||||
}
|
||||
|
||||
// WD-EDIT
|
||||
public void FilterSponsor(string[] sponsorMarkings, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||
public void FilterSponsor(
|
||||
string[] sponsorMarkings,
|
||||
MarkingManager? markingManager = null,
|
||||
IPrototypeManager? prototypeManager = null)
|
||||
{
|
||||
IoCManager.Resolve(ref markingManager);
|
||||
IoCManager.Resolve(ref prototypeManager);
|
||||
@@ -319,11 +337,12 @@ public sealed partial class MarkingSet
|
||||
if (markingManager.Markings.TryGetValue(points.DefaultMarkings[index], out var prototype))
|
||||
{
|
||||
var colors = MarkingColoring.GetMarkingLayerColors(
|
||||
prototype,
|
||||
skinColor,
|
||||
eyeColor,
|
||||
this
|
||||
);
|
||||
prototype,
|
||||
skinColor,
|
||||
eyeColor,
|
||||
this
|
||||
);
|
||||
|
||||
var marking = new Marking(points.DefaultMarkings[index], colors);
|
||||
|
||||
AddBack(category, marking);
|
||||
@@ -398,7 +417,6 @@ public sealed partial class MarkingSet
|
||||
Markings[category] = markings;
|
||||
}
|
||||
|
||||
|
||||
markings.Add(marking);
|
||||
}
|
||||
|
||||
@@ -854,7 +872,8 @@ public sealed class MarkingsEnumerator : IEnumerator<Marking>
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
|
||||
35
Content.Shared/Humanoid/Prototypes/BodyTypePrototype.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Humanoid.Prototypes
|
||||
{
|
||||
[Prototype("bodyType")]
|
||||
public sealed class BodyTypePrototype : IPrototype
|
||||
{
|
||||
/// <summary>
|
||||
/// Which sex can't use this body type.
|
||||
/// </summary>
|
||||
[DataField("sexRestrictions")]
|
||||
public List<string> SexRestrictions = new();
|
||||
|
||||
/// <summary>
|
||||
/// Sprites that this species will use on the given humanoid
|
||||
/// visual layer. If a key entry is empty, it is assumed that the
|
||||
/// visual layer will not be in use on this species, and will
|
||||
/// be ignored.
|
||||
/// </summary>
|
||||
[DataField("sprites", required: true)]
|
||||
public Dictionary<HumanoidVisualLayers, string> Sprites = new();
|
||||
|
||||
/// <summary>
|
||||
/// User visible name of the body type.
|
||||
/// </summary>
|
||||
[DataField("name", required: true)]
|
||||
public string Name { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Prototype ID of the body type.
|
||||
/// </summary>
|
||||
[IdDataField]
|
||||
public string ID { get; } = default!;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Humanoid.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
/*/// <summary>
|
||||
/// Base sprites for a species (e.g., what replaces the empty tagged layer,
|
||||
/// or settings per layer)
|
||||
/// </summary>
|
||||
@@ -21,7 +21,7 @@ public sealed partial class HumanoidSpeciesBaseSpritesPrototype : IPrototype
|
||||
/// </summary>
|
||||
[DataField("sprites", required: true)]
|
||||
public Dictionary<HumanoidVisualLayers, string> Sprites = new();
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Humanoid species sprite layer. This is what defines the base layer of
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Humanoid.Prototypes;
|
||||
|
||||
@@ -18,6 +19,9 @@ public sealed partial class SpeciesPrototype : IPrototype
|
||||
[DataField("name", required: true)]
|
||||
public string Name { get; private set; } = default!;
|
||||
|
||||
[DataField("bodyTypes", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<BodyTypePrototype>))]
|
||||
public List<string> BodyTypes { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Descriptor. Unused...? This is intended
|
||||
/// for an eventual integration into IdentitySystem
|
||||
@@ -41,8 +45,8 @@ public sealed partial class SpeciesPrototype : IPrototype
|
||||
// sprite layout, and leave this null. Keep in mind that this will disable
|
||||
// sprite accessories.
|
||||
|
||||
[DataField("sprites")]
|
||||
public string SpriteSet { get; private set; } = default!;
|
||||
// [DataField("sprites")]
|
||||
// public string SpriteSet { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Default skin tone for this species. This applies for non-human skin tones.
|
||||
@@ -66,13 +70,13 @@ public sealed partial class SpeciesPrototype : IPrototype
|
||||
/// <summary>
|
||||
/// Humanoid species variant used by this entity.
|
||||
/// </summary>
|
||||
[DataField("prototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Prototype { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Prototype used by the species for the dress-up doll in various menus.
|
||||
/// </summary>
|
||||
[DataField("dollPrototype", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
[DataField("dollPrototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string DollPrototype { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Decals;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
@@ -26,12 +25,15 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
|
||||
[ValidatePrototypeId<SpeciesPrototype>]
|
||||
public const string DefaultSpecies = "Human";
|
||||
|
||||
public const string DefaultBodyType = "HumanNormal";
|
||||
public const string DefaultVoice = "Eugene";
|
||||
|
||||
public static readonly Dictionary<Sex, string> DefaultSexVoice = new()
|
||||
{
|
||||
{Sex.Male, "Eugene"},
|
||||
{Sex.Female, "Kseniya"},
|
||||
{Sex.Unsexed, "Xenia"},
|
||||
{ Sex.Male, "Eugene" },
|
||||
{ Sex.Female, "Kseniya" },
|
||||
{ Sex.Unsexed, "Xenia" },
|
||||
};
|
||||
|
||||
public override void Initialize()
|
||||
@@ -69,7 +71,8 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="uid">Humanoid mob's UID</param>
|
||||
/// <param name="layer">Layer to toggle visibility for</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetLayerVisibility(EntityUid uid,
|
||||
public void SetLayerVisibility(
|
||||
EntityUid uid,
|
||||
HumanoidVisualLayers layer,
|
||||
bool visible,
|
||||
bool permanent = false,
|
||||
@@ -92,7 +95,11 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="visible">The visibility state of the layers given</param>
|
||||
/// <param name="permanent">If this is a permanent change, or temporary. Permanent layers are stored in their own hash set.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetLayersVisibility(EntityUid uid, IEnumerable<HumanoidVisualLayers> layers, bool visible, bool permanent = false,
|
||||
public void SetLayersVisibility(
|
||||
EntityUid uid,
|
||||
IEnumerable<HumanoidVisualLayers> layers,
|
||||
bool visible,
|
||||
bool permanent = false,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
@@ -141,7 +148,11 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="species">The species to set the mob to. Will return if the species prototype was invalid.</param>
|
||||
/// <param name="sync">Whether to immediately synchronize this to the humanoid mob, or not.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetSpecies(EntityUid uid, string species, bool sync = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void SetSpecies(
|
||||
EntityUid uid,
|
||||
string species,
|
||||
bool sync = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid) || !_prototypeManager.TryIndex<SpeciesPrototype>(species, out var prototype))
|
||||
{
|
||||
@@ -149,12 +160,14 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
}
|
||||
|
||||
humanoid.Species = species;
|
||||
humanoid.MarkingSet.EnsureSpecies(species, humanoid.SkinColor, _markingManager);
|
||||
humanoid.MarkingSet.EnsureSpecies(species, humanoid.BodyType, humanoid.SkinColor, _markingManager);
|
||||
var oldMarkings = humanoid.MarkingSet.GetForwardEnumerator().ToList();
|
||||
humanoid.MarkingSet = new(oldMarkings, prototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
humanoid.MarkingSet = new MarkingSet(oldMarkings, prototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
|
||||
if (sync)
|
||||
Dirty(humanoid);
|
||||
{
|
||||
Dirty(uid, humanoid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -166,7 +179,12 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="sync">Whether to synchronize this to the humanoid mob, or not.</param>
|
||||
/// <param name="verify">Whether to verify the skin color can be set on this humanoid or not</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public virtual void SetSkinColor(EntityUid uid, Color skinColor, bool sync = true, bool verify = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public virtual void SetSkinColor(
|
||||
EntityUid uid,
|
||||
Color skinColor,
|
||||
bool sync = true,
|
||||
bool verify = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
return;
|
||||
@@ -196,7 +214,11 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="id">The ID of the sprite to use. See <see cref="HumanoidSpeciesSpriteLayer"/>.</param>
|
||||
/// <param name="sync">Whether to synchronize this to the humanoid mob, or not.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void SetBaseLayerId(EntityUid uid, HumanoidVisualLayers layer, string? id, bool sync = true,
|
||||
public void SetBaseLayerId(
|
||||
EntityUid uid,
|
||||
HumanoidVisualLayers layer,
|
||||
string? id,
|
||||
bool sync = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
@@ -218,7 +240,12 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="uid">The humanoid mob's UID.</param>
|
||||
/// <param name="layer">The layer to target on this humanoid mob.</param>
|
||||
/// <param name="color">The color to set this base layer to.</param>
|
||||
public void SetBaseLayerColor(EntityUid uid, HumanoidVisualLayers layer, Color? color, bool sync = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void SetBaseLayerColor(
|
||||
EntityUid uid,
|
||||
HumanoidVisualLayers layer,
|
||||
Color? color,
|
||||
bool sync = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
return;
|
||||
@@ -255,13 +282,27 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
public List<BodyTypePrototype> GetValidBodyTypes(SpeciesPrototype species, Sex sex)
|
||||
{
|
||||
return species.BodyTypes.Select(protoId => _prototypeManager.Index<BodyTypePrototype>(protoId))
|
||||
.Where(proto => !proto.SexRestrictions.Contains(sex.ToString())).ToList();
|
||||
}
|
||||
|
||||
public static bool IsBodyTypeValid(BodyTypePrototype bodyType, SpeciesPrototype species, Sex sex)
|
||||
{
|
||||
return species.BodyTypes.Contains(bodyType.ID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a humanoid character profile directly onto this humanoid mob.
|
||||
/// </summary>
|
||||
/// <param name="uid">The mob's entity UID.</param>
|
||||
/// <param name="profile">The character profile to load.</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public virtual void LoadProfile(EntityUid uid, HumanoidCharacterProfile profile, HumanoidAppearanceComponent? humanoid = null)
|
||||
public virtual void LoadProfile(
|
||||
EntityUid uid,
|
||||
HumanoidCharacterProfile profile,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
{
|
||||
@@ -295,10 +336,15 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
|
||||
// Hair/facial hair - this may eventually be deprecated.
|
||||
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha) : profile.Appearance.HairColor;
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha) : profile.Appearance.FacialHairColor;
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha,
|
||||
_prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha)
|
||||
: profile.Appearance.HairColor;
|
||||
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair,
|
||||
out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha)
|
||||
: profile.Appearance.FacialHairColor;
|
||||
|
||||
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
|
||||
_markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _prototypeManager))
|
||||
@@ -312,7 +358,9 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
|
||||
}
|
||||
|
||||
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.BodyType, profile.Appearance.SkinColor,
|
||||
_markingManager,
|
||||
_prototypeManager);
|
||||
|
||||
// Finally adding marking with forced colors
|
||||
foreach (var (marking, prototype) in markingFColored)
|
||||
@@ -323,6 +371,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
profile.Appearance.EyeColor,
|
||||
humanoid.MarkingSet
|
||||
);
|
||||
|
||||
AddMarking(uid, marking.MarkingId, markingColors, false);
|
||||
}
|
||||
|
||||
@@ -348,7 +397,13 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="sync">Whether to immediately sync this marking or not</param>
|
||||
/// <param name="forced">If this marking was forced (ignores marking points)</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void AddMarking(EntityUid uid, string marking, Color? color = null, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void AddMarking(
|
||||
EntityUid uid,
|
||||
string marking,
|
||||
Color? color = null,
|
||||
bool sync = true,
|
||||
bool forced = false,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
@@ -378,6 +433,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
humanoid.MarkingSet.EnsureDefault(humanoid.SkinColor, humanoid.EyeColor, _markingManager);
|
||||
}
|
||||
|
||||
@@ -390,7 +446,13 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||
/// <param name="sync">Whether to immediately sync this marking or not</param>
|
||||
/// <param name="forced">If this marking was forced (ignores marking points)</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void AddMarking(EntityUid uid, string marking, IReadOnlyList<Color> colors, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null)
|
||||
public void AddMarking(
|
||||
EntityUid uid,
|
||||
string marking,
|
||||
IReadOnlyList<Color> colors,
|
||||
bool sync = true,
|
||||
bool forced = false,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
|
||||
@@ -44,6 +44,7 @@ public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
||||
public HumanoidMarkingModifierState(
|
||||
MarkingSet markingSet,
|
||||
string species,
|
||||
string bodyType,
|
||||
Sex sex,
|
||||
Color skinColor,
|
||||
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> customBaseLayers
|
||||
@@ -51,6 +52,7 @@ public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
||||
{
|
||||
MarkingSet = markingSet;
|
||||
Species = species;
|
||||
BodyType = bodyType;
|
||||
Sex = sex;
|
||||
SkinColor = skinColor;
|
||||
CustomBaseLayers = customBaseLayers;
|
||||
@@ -60,6 +62,7 @@ public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
||||
public string Species { get; }
|
||||
public Sex Sex { get; }
|
||||
public Color SkinColor { get; }
|
||||
public string BodyType { get; }
|
||||
public Color EyeColor { get; }
|
||||
public Color? HairColor { get; }
|
||||
public Color? FacialHairColor { get; }
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Traits;
|
||||
using Content.Shared._White.TTS;
|
||||
@@ -15,8 +13,6 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Administration;
|
||||
|
||||
namespace Content.Shared.Preferences
|
||||
{
|
||||
@@ -45,6 +41,7 @@ namespace Content.Shared.Preferences
|
||||
Sex sex,
|
||||
string voice,
|
||||
Gender gender,
|
||||
string bodyType,
|
||||
HumanoidCharacterAppearance appearance,
|
||||
ClothingPreference clothing,
|
||||
BackpackPreference backpack,
|
||||
@@ -64,6 +61,7 @@ namespace Content.Shared.Preferences
|
||||
Age = age;
|
||||
Sex = sex;
|
||||
Gender = gender;
|
||||
BodyType = bodyType;
|
||||
Appearance = appearance;
|
||||
Clothing = clothing;
|
||||
Backpack = backpack;
|
||||
@@ -80,14 +78,17 @@ namespace Content.Shared.Preferences
|
||||
Dictionary<string, JobPriority> jobPriorities,
|
||||
List<string> antagPreferences,
|
||||
List<string> traitPreferences)
|
||||
: this(other.Name, other.ClownName, other.MimeName, other.BorgName, other.FlavorText, other.Species, other.Voice, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack, other.SpawnPriority,
|
||||
: this(other.Name, other.ClownName, other.MimeName, other.BorgName, other.FlavorText, other.Species,
|
||||
other.Voice, other.Age, other.Sex, other.Gender, other.BodyType, other.Appearance, other.Clothing,
|
||||
other.Backpack, other.SpawnPriority,
|
||||
jobPriorities, other.PreferenceUnavailable, antagPreferences, traitPreferences)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Copy constructor</summary>
|
||||
private HumanoidCharacterProfile(HumanoidCharacterProfile other)
|
||||
: this(other, new Dictionary<string, JobPriority>(other.JobPriorities), new List<string>(other.AntagPreferences), new List<string>(other.TraitPreferences))
|
||||
: this(other, new Dictionary<string, JobPriority>(other.JobPriorities),
|
||||
new List<string>(other.AntagPreferences), new List<string>(other.TraitPreferences))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -102,6 +103,7 @@ namespace Content.Shared.Preferences
|
||||
int age,
|
||||
Sex sex,
|
||||
Gender gender,
|
||||
string bodyType,
|
||||
HumanoidCharacterAppearance appearance,
|
||||
ClothingPreference clothing,
|
||||
BackpackPreference backpack,
|
||||
@@ -110,7 +112,8 @@ namespace Content.Shared.Preferences
|
||||
PreferenceUnavailableMode preferenceUnavailable,
|
||||
IReadOnlyList<string> antagPreferences,
|
||||
IReadOnlyList<string> traitPreferences)
|
||||
: this(name, clownName, mimeName, borgName, flavortext, species, age, sex, voice, gender, appearance, clothing, backpack, spawnPriority, new Dictionary<string, JobPriority>(jobPriorities),
|
||||
: this(name, clownName, mimeName, borgName, flavortext, species, age, sex, voice, gender, bodyType,
|
||||
appearance, clothing, backpack, spawnPriority, new Dictionary<string, JobPriority>(jobPriorities),
|
||||
preferenceUnavailable, new List<string>(antagPreferences), new List<string>(traitPreferences))
|
||||
{
|
||||
}
|
||||
@@ -131,13 +134,14 @@ namespace Content.Shared.Preferences
|
||||
18,
|
||||
Sex.Male,
|
||||
Gender.Male,
|
||||
SharedHumanoidAppearanceSystem.DefaultBodyType,
|
||||
new HumanoidCharacterAppearance(),
|
||||
ClothingPreference.Jumpsuit,
|
||||
BackpackPreference.Backpack,
|
||||
SpawnPriorityPreference.None,
|
||||
new Dictionary<string, JobPriority>
|
||||
{
|
||||
{SharedGameTicker.FallbackOverflowJob, JobPriority.High}
|
||||
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High }
|
||||
},
|
||||
PreferenceUnavailableMode.SpawnAsOverflow,
|
||||
new List<string>(),
|
||||
@@ -150,7 +154,8 @@ namespace Content.Shared.Preferences
|
||||
/// </summary>
|
||||
/// <param name="species">The species to use in this default profile. The default species is <see cref="SharedHumanoidAppearanceSystem.DefaultSpecies"/>.</param>
|
||||
/// <returns>Humanoid character profile with default settings.</returns>
|
||||
public static HumanoidCharacterProfile DefaultWithSpecies(string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
|
||||
public static HumanoidCharacterProfile DefaultWithSpecies(
|
||||
string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
|
||||
{
|
||||
return new(
|
||||
"John Doe",
|
||||
@@ -163,13 +168,14 @@ namespace Content.Shared.Preferences
|
||||
18,
|
||||
Sex.Male,
|
||||
Gender.Male,
|
||||
SharedHumanoidAppearanceSystem.DefaultBodyType,
|
||||
HumanoidCharacterAppearance.DefaultWithSpecies(species),
|
||||
ClothingPreference.Jumpsuit,
|
||||
BackpackPreference.Backpack,
|
||||
SpawnPriorityPreference.None,
|
||||
new Dictionary<string, JobPriority>
|
||||
{
|
||||
{SharedGameTicker.FallbackOverflowJob, JobPriority.High}
|
||||
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High }
|
||||
},
|
||||
PreferenceUnavailableMode.SpawnAsOverflow,
|
||||
new List<string>(),
|
||||
@@ -191,17 +197,21 @@ namespace Content.Shared.Preferences
|
||||
return RandomWithSpecies(species);
|
||||
}
|
||||
|
||||
public static HumanoidCharacterProfile RandomWithSpecies(string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
|
||||
public static HumanoidCharacterProfile RandomWithSpecies(
|
||||
string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
|
||||
{
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
|
||||
var sex = Sex.Unsexed;
|
||||
var age = 18;
|
||||
var bodyType = SharedHumanoidAppearanceSystem.DefaultBodyType;
|
||||
if (prototypeManager.TryIndex<SpeciesPrototype>(species, out var speciesPrototype))
|
||||
{
|
||||
sex = random.Pick(speciesPrototype.Sexes);
|
||||
age = random.Next(speciesPrototype.MinAge, speciesPrototype.OldAge); // people don't look and keep making 119 year old characters with zero rp, cap it at middle aged
|
||||
age = random.Next(speciesPrototype.MinAge,
|
||||
speciesPrototype
|
||||
.OldAge); // people don't look and keep making 119 year old characters with zero rp, cap it at middle aged
|
||||
}
|
||||
|
||||
var voiceId = random.Pick(prototypeManager
|
||||
@@ -226,18 +236,25 @@ namespace Content.Shared.Preferences
|
||||
var mimeName = GetMimeName();
|
||||
var borgName = GetBorgName();
|
||||
|
||||
return new HumanoidCharacterProfile(name, clownName, mimeName, borgName, "", species, voiceId, age, sex, gender, HumanoidCharacterAppearance.Random(species, sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack, SpawnPriorityPreference.None,
|
||||
return new HumanoidCharacterProfile(name, clownName, mimeName, borgName, "", species, voiceId, age, sex,
|
||||
gender, bodyType, HumanoidCharacterAppearance.Random(species, sex), ClothingPreference.Jumpsuit,
|
||||
BackpackPreference.Backpack, SpawnPriorityPreference.None,
|
||||
new Dictionary<string, JobPriority>
|
||||
{
|
||||
{SharedGameTicker.FallbackOverflowJob, JobPriority.High},
|
||||
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High },
|
||||
}, PreferenceUnavailableMode.StayInLobby, new List<string>(), new List<string>());
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public string ClownName { get; private set; }
|
||||
|
||||
public string MimeName { get; private set; }
|
||||
|
||||
public string BorgName { get; private set; }
|
||||
|
||||
public string FlavorText { get; private set; }
|
||||
|
||||
public string Species { get; private set; }
|
||||
|
||||
public string Voice { get; private set; }
|
||||
@@ -251,24 +268,38 @@ namespace Content.Shared.Preferences
|
||||
[DataField("gender")]
|
||||
public Gender Gender { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public string BodyType { get; private set; }
|
||||
|
||||
public ICharacterAppearance CharacterAppearance => Appearance;
|
||||
|
||||
[DataField("appearance")]
|
||||
public HumanoidCharacterAppearance Appearance { get; private set; }
|
||||
public ClothingPreference Clothing { get; private set; }
|
||||
public BackpackPreference Backpack { get; private set; }
|
||||
public SpawnPriorityPreference SpawnPriority { get; private set; }
|
||||
public IReadOnlyDictionary<string, JobPriority> JobPriorities => _jobPriorities;
|
||||
public IReadOnlyList<string> AntagPreferences => _antagPreferences;
|
||||
public IReadOnlyList<string> TraitPreferences => _traitPreferences;
|
||||
public PreferenceUnavailableMode PreferenceUnavailable { get; private set; }
|
||||
|
||||
public ClothingPreference Clothing { get; private set; }
|
||||
|
||||
public BackpackPreference Backpack { get; private set; }
|
||||
|
||||
public SpawnPriorityPreference SpawnPriority { get; private set; }
|
||||
|
||||
public IReadOnlyDictionary<string, JobPriority> JobPriorities => _jobPriorities;
|
||||
|
||||
public IReadOnlyList<string> AntagPreferences => _antagPreferences;
|
||||
|
||||
public IReadOnlyList<string> TraitPreferences => _traitPreferences;
|
||||
|
||||
public PreferenceUnavailableMode PreferenceUnavailable { get; private set; }
|
||||
|
||||
public HumanoidCharacterProfile WithVoice(string voice)
|
||||
{
|
||||
return new(this) { Voice = voice };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithBodyType(string bodyType)
|
||||
{
|
||||
return new(this) { BodyType = bodyType };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithName(string name)
|
||||
{
|
||||
return new(this) { Name = name };
|
||||
@@ -278,10 +309,12 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
return new(this) { ClownName = name };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithMimeName(string name)
|
||||
{
|
||||
return new(this) { MimeName = name };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithBorgName(string name)
|
||||
{
|
||||
return new(this) { BorgName = name };
|
||||
@@ -312,7 +345,6 @@ namespace Content.Shared.Preferences
|
||||
return new(this) { Species = species };
|
||||
}
|
||||
|
||||
|
||||
public HumanoidCharacterProfile WithCharacterAppearance(HumanoidCharacterAppearance appearance)
|
||||
{
|
||||
return new(this) { Appearance = appearance };
|
||||
@@ -322,14 +354,17 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
return new(this) { Clothing = clothing };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithBackpackPreference(BackpackPreference backpack)
|
||||
{
|
||||
return new(this) { Backpack = backpack };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithSpawnPriorityPreference(SpawnPriorityPreference spawnPriority)
|
||||
{
|
||||
return new(this) { SpawnPriority = spawnPriority };
|
||||
}
|
||||
|
||||
public HumanoidCharacterProfile WithJobPriorities(IEnumerable<KeyValuePair<string, JobPriority>> jobPriorities)
|
||||
{
|
||||
return new(this, new Dictionary<string, JobPriority>(jobPriorities), _antagPreferences, _traitPreferences);
|
||||
@@ -346,6 +381,7 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
dictionary[jobId] = priority;
|
||||
}
|
||||
|
||||
return new(this, dictionary, _antagPreferences, _traitPreferences);
|
||||
}
|
||||
|
||||
@@ -376,6 +412,7 @@ namespace Content.Shared.Preferences
|
||||
list.Remove(antagId);
|
||||
}
|
||||
}
|
||||
|
||||
return new(this, _jobPriorities, list, _traitPreferences);
|
||||
}
|
||||
|
||||
@@ -398,6 +435,7 @@ namespace Content.Shared.Preferences
|
||||
list.Remove(traitId);
|
||||
}
|
||||
}
|
||||
|
||||
return new(this, _jobPriorities, _antagPreferences, list);
|
||||
}
|
||||
|
||||
@@ -411,21 +449,54 @@ namespace Content.Shared.Preferences
|
||||
|
||||
public bool MemberwiseEquals(ICharacterProfile maybeOther)
|
||||
{
|
||||
if (maybeOther is not HumanoidCharacterProfile other) return false;
|
||||
if (Name != other.Name) return false;
|
||||
if (ClownName != other.ClownName) return false;
|
||||
if (MimeName != other.MimeName) return false;
|
||||
if (BorgName != other.BorgName) return false;
|
||||
if (Age != other.Age) return false;
|
||||
if (Sex != other.Sex) return false;
|
||||
if (Gender != other.Gender) return false;
|
||||
if (PreferenceUnavailable != other.PreferenceUnavailable) return false;
|
||||
if (Clothing != other.Clothing) return false;
|
||||
if (Backpack != other.Backpack) return false;
|
||||
if (SpawnPriority != other.SpawnPriority) return false;
|
||||
if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false;
|
||||
if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false;
|
||||
if (!_traitPreferences.SequenceEqual(other._traitPreferences)) return false;
|
||||
if (maybeOther is not HumanoidCharacterProfile other)
|
||||
return false;
|
||||
|
||||
if (Name != other.Name)
|
||||
return false;
|
||||
|
||||
if (ClownName != other.ClownName)
|
||||
return false;
|
||||
|
||||
if (MimeName != other.MimeName)
|
||||
return false;
|
||||
|
||||
if (BorgName != other.BorgName)
|
||||
return false;
|
||||
|
||||
if (Age != other.Age)
|
||||
return false;
|
||||
|
||||
if (Sex != other.Sex)
|
||||
return false;
|
||||
|
||||
if (Gender != other.Gender)
|
||||
return false;
|
||||
|
||||
if (BodyType != other.BodyType)
|
||||
return false;
|
||||
|
||||
if (PreferenceUnavailable != other.PreferenceUnavailable)
|
||||
return false;
|
||||
|
||||
if (Clothing != other.Clothing)
|
||||
return false;
|
||||
|
||||
if (Backpack != other.Backpack)
|
||||
return false;
|
||||
|
||||
if (SpawnPriority != other.SpawnPriority)
|
||||
return false;
|
||||
|
||||
if (!_jobPriorities.SequenceEqual(other._jobPriorities))
|
||||
return false;
|
||||
|
||||
if (!_antagPreferences.SequenceEqual(other._antagPreferences))
|
||||
return false;
|
||||
|
||||
if (!_traitPreferences.SequenceEqual(other._traitPreferences))
|
||||
return false;
|
||||
|
||||
return Appearance.MemberwiseEquals(other.Appearance);
|
||||
}
|
||||
|
||||
@@ -448,10 +519,10 @@ namespace Content.Shared.Preferences
|
||||
|
||||
var sex = Sex switch
|
||||
{
|
||||
Sex.Male => Sex.Male,
|
||||
Sex.Female => Sex.Female,
|
||||
Sex.Male => Sex.Male,
|
||||
Sex.Female => Sex.Female,
|
||||
Sex.Unsexed => Sex.Unsexed,
|
||||
_ => Sex.Male // Invalid enum values.
|
||||
_ => Sex.Male // Invalid enum values.
|
||||
};
|
||||
|
||||
// ensure the species can be that sex and their age fits the founds
|
||||
@@ -462,16 +533,24 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
sex = speciesPrototype.Sexes[0];
|
||||
}
|
||||
|
||||
age = Math.Clamp(Age, speciesPrototype.MinAge, speciesPrototype.MaxAge);
|
||||
|
||||
if (!prototypeManager.TryIndex<BodyTypePrototype>(BodyType, out var bodyType) ||
|
||||
!SharedHumanoidAppearanceSystem.IsBodyTypeValid(bodyType, speciesPrototype, Sex))
|
||||
{
|
||||
BodyType =
|
||||
prototypeManager.Index<BodyTypePrototype>(SharedHumanoidAppearanceSystem.DefaultBodyType).ID;
|
||||
}
|
||||
}
|
||||
|
||||
var gender = Gender switch
|
||||
{
|
||||
Gender.Epicene => Gender.Epicene,
|
||||
Gender.Female => Gender.Female,
|
||||
Gender.Male => Gender.Male,
|
||||
Gender.Neuter => Gender.Neuter,
|
||||
_ => Gender.Epicene // Invalid enum values.
|
||||
Gender.Female => Gender.Female,
|
||||
Gender.Male => Gender.Male,
|
||||
Gender.Neuter => Gender.Neuter,
|
||||
_ => Gender.Epicene // Invalid enum values.
|
||||
};
|
||||
|
||||
string name;
|
||||
@@ -490,6 +569,7 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
name = Name;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(ClownName))
|
||||
{
|
||||
clownName = GetClownName();
|
||||
@@ -502,6 +582,7 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
clownName = ClownName;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(MimeName))
|
||||
{
|
||||
mimeName = GetMimeName();
|
||||
@@ -514,6 +595,7 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
mimeName = MimeName;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(BorgName))
|
||||
{
|
||||
borgName = GetBorgName();
|
||||
@@ -545,14 +627,17 @@ namespace Content.Shared.Preferences
|
||||
{
|
||||
// This regex replaces the first character of the first and last words of the name with their uppercase version
|
||||
name = Regex.Replace(name,
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
|
||||
clownName = Regex.Replace(clownName,
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
|
||||
mimeName = Regex.Replace(mimeName,
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
|
||||
borgName = Regex.Replace(borgName,
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
@@ -577,7 +662,7 @@ namespace Content.Shared.Preferences
|
||||
}
|
||||
|
||||
// WD-EDIT
|
||||
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, sponsorMarkings);
|
||||
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, BodyType, sponsorMarkings);
|
||||
// WD-EDIT
|
||||
|
||||
var prefsUnavailableMode = PreferenceUnavailable switch
|
||||
@@ -589,35 +674,35 @@ namespace Content.Shared.Preferences
|
||||
|
||||
var clothing = Clothing switch
|
||||
{
|
||||
ClothingPreference.Jumpsuit => ClothingPreference.Jumpsuit,
|
||||
ClothingPreference.Jumpsuit => ClothingPreference.Jumpsuit,
|
||||
ClothingPreference.Jumpskirt => ClothingPreference.Jumpskirt,
|
||||
_ => ClothingPreference.Jumpsuit // Invalid enum values.
|
||||
_ => ClothingPreference.Jumpsuit // Invalid enum values.
|
||||
};
|
||||
|
||||
var backpack = Backpack switch
|
||||
{
|
||||
BackpackPreference.Backpack => BackpackPreference.Backpack,
|
||||
BackpackPreference.Satchel => BackpackPreference.Satchel,
|
||||
BackpackPreference.Backpack => BackpackPreference.Backpack,
|
||||
BackpackPreference.Satchel => BackpackPreference.Satchel,
|
||||
BackpackPreference.Duffelbag => BackpackPreference.Duffelbag,
|
||||
_ => BackpackPreference.Backpack // Invalid enum values.
|
||||
_ => BackpackPreference.Backpack // Invalid enum values.
|
||||
};
|
||||
|
||||
var spawnPriority = SpawnPriority switch
|
||||
{
|
||||
SpawnPriorityPreference.None => SpawnPriorityPreference.None,
|
||||
SpawnPriorityPreference.Arrivals => SpawnPriorityPreference.Arrivals,
|
||||
SpawnPriorityPreference.None => SpawnPriorityPreference.None,
|
||||
SpawnPriorityPreference.Arrivals => SpawnPriorityPreference.Arrivals,
|
||||
SpawnPriorityPreference.Cryosleep => SpawnPriorityPreference.Cryosleep,
|
||||
_ => SpawnPriorityPreference.None // Invalid enum values.
|
||||
_ => SpawnPriorityPreference.None // Invalid enum values.
|
||||
};
|
||||
|
||||
var priorities = new Dictionary<string, JobPriority>(JobPriorities
|
||||
.Where(p => prototypeManager.HasIndex<JobPrototype>(p.Key) && p.Value switch
|
||||
{
|
||||
JobPriority.Never => false, // Drop never since that's assumed default.
|
||||
JobPriority.Low => true,
|
||||
JobPriority.Never => false, // Drop never since that's assumed default.
|
||||
JobPriority.Low => true,
|
||||
JobPriority.Medium => true,
|
||||
JobPriority.High => true,
|
||||
_ => false
|
||||
JobPriority.High => true,
|
||||
_ => false
|
||||
}));
|
||||
|
||||
var antags = AntagPreferences
|
||||
@@ -625,8 +710,8 @@ namespace Content.Shared.Preferences
|
||||
.ToList();
|
||||
|
||||
var traits = TraitPreferences
|
||||
.Where(prototypeManager.HasIndex<TraitPrototype>)
|
||||
.ToList();
|
||||
.Where(prototypeManager.HasIndex<TraitPrototype>)
|
||||
.ToList();
|
||||
|
||||
Name = name;
|
||||
ClownName = clownName;
|
||||
|
||||
@@ -37,15 +37,6 @@ marking-HumanHairBusiness3 = Business Hair 3
|
||||
marking-HumanHairBusiness4 = Business Hair 4
|
||||
marking-HumanHairBuzzcut = Buzzcut
|
||||
marking-HumanHairCia = CIA
|
||||
marking-HumanHairClassicAfro = Classic Afro
|
||||
marking-HumanHairClassicBigAfro = Classic Big Afro
|
||||
marking-HumanHairClassicBusiness = Classic Business Hair
|
||||
marking-HumanHairClassicCia = Classic CIA
|
||||
marking-HumanHairClassicCornrows2 = Classic Cornrows 2
|
||||
marking-HumanHairClassicFloorlengthBedhead = Classic Floorlength Bedhead
|
||||
marking-HumanHairClassicModern = Classic Modern
|
||||
marking-HumanHairClassicMulder = Classic Mulder
|
||||
marking-HumanHairClassicWisp = Classic Wisp
|
||||
marking-HumanHairCoffeehouse = Coffee House
|
||||
marking-HumanHairCombover = Combover
|
||||
marking-HumanHairCornrows = Cornrows
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: "torso_m"
|
||||
state: "torso"
|
||||
- type: Extractable
|
||||
juiceSolution:
|
||||
reagents:
|
||||
@@ -30,6 +30,14 @@
|
||||
- ReagentId: Blood
|
||||
Quantity: 20
|
||||
|
||||
- type: entity
|
||||
id: TorsoHumanSlim
|
||||
name: "human torso"
|
||||
parent: TorsoHuman
|
||||
components:
|
||||
- type: Sprite
|
||||
state: "torso_slim"
|
||||
|
||||
- type: entity
|
||||
id: HeadHuman
|
||||
name: "human head"
|
||||
@@ -37,7 +45,7 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: "head_m"
|
||||
state: "head"
|
||||
- type: Extractable
|
||||
juiceSolution:
|
||||
reagents:
|
||||
@@ -46,6 +54,13 @@
|
||||
- ReagentId: Blood
|
||||
Quantity: 10
|
||||
|
||||
- type: entity
|
||||
id: HeadHumanSlim
|
||||
parent: HeadHuman
|
||||
components:
|
||||
- type: Sprite
|
||||
state: "head_slim"
|
||||
|
||||
- type: entity
|
||||
id: LeftArmHuman
|
||||
name: "left human arm"
|
||||
|
||||
@@ -271,69 +271,6 @@
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: cia
|
||||
- type: marking
|
||||
id: HumanHairClassicAfro
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicafro
|
||||
- type: marking
|
||||
id: HumanHairClassicBigAfro
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicbigafro
|
||||
- type: marking
|
||||
id: HumanHairClassicBusiness
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicbusiness
|
||||
- type: marking
|
||||
id: HumanHairClassicCia
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classiccia
|
||||
- type: marking
|
||||
id: HumanHairClassicCornrows2
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classiccornrows2
|
||||
- type: marking
|
||||
id: HumanHairClassicFloorlengthBedhead
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicfloorlength_bedhead
|
||||
- type: marking
|
||||
id: HumanHairClassicModern
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicmodern
|
||||
- type: marking
|
||||
id: HumanHairClassicMulder
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicmulder
|
||||
- type: marking
|
||||
id: HumanHairClassicWisp
|
||||
bodyPart: Hair
|
||||
markingCategory: Hair
|
||||
sprites:
|
||||
- sprite: Mobs/Customization/human_hair.rsi
|
||||
state: classicwisp
|
||||
- type: marking
|
||||
id: HumanHairCoffeehouse
|
||||
bodyPart: Hair
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-arachnid
|
||||
roundStart: true
|
||||
prototype: MobArachnid
|
||||
sprites: MobArachnidSprites
|
||||
bodyTypes:
|
||||
- ArachnidNormal
|
||||
defaultSkinTone: "#385878"
|
||||
markingLimits: MobArachnidMarkingLimits
|
||||
dollPrototype: MobArachnidDummy
|
||||
@@ -15,25 +16,6 @@
|
||||
sexes:
|
||||
- Unsexed
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobArachnidSprites
|
||||
sprites:
|
||||
Head: MobArachnidHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobArachnidTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidAnyMarking
|
||||
LArm: MobArachnidLArm
|
||||
RArm: MobArachnidRArm
|
||||
LHand: MobArachnidLHand
|
||||
RHand: MobArachnidRHand
|
||||
LLeg: MobArachnidLLeg
|
||||
RLeg: MobArachnidRLeg
|
||||
LFoot: MobArachnidLFoot
|
||||
RFoot: MobArachnidRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobArachnidMarkingLimits
|
||||
onlyWhitelisted: true
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-diona
|
||||
roundStart: true
|
||||
prototype: MobDiona
|
||||
sprites: MobDionaSprites
|
||||
bodyTypes:
|
||||
- DionaNormal
|
||||
defaultSkinTone: "#cdb369"
|
||||
markingLimits: MobDionaMarkingLimits
|
||||
dollPrototype: MobDionaDummy
|
||||
@@ -14,23 +15,6 @@
|
||||
femaleLastNames: DionaLast
|
||||
naming: TheFirstofLast
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobDionaSprites
|
||||
sprites:
|
||||
Head: MobDionaHead
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Chest: MobDionaTorso
|
||||
Eyes: MobDionaEyes
|
||||
LArm: MobDionaLArm
|
||||
RArm: MobDionaRArm
|
||||
LHand: MobDionaLHand
|
||||
RHand: MobDionaRHand
|
||||
LLeg: MobDionaLLeg
|
||||
RLeg: MobDionaRLeg
|
||||
LFoot: MobDionaLFoot
|
||||
RFoot: MobDionaRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobDionaMarkingLimits
|
||||
onlyWhitelisted: true
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-dwarf
|
||||
roundStart: true
|
||||
prototype: MobDwarf
|
||||
sprites: MobHumanSprites
|
||||
bodyTypes:
|
||||
- HumanNormal
|
||||
markingLimits: MobHumanMarkingLimits
|
||||
dollPrototype: MobDwarfDummy
|
||||
skinColoration: HumanToned
|
||||
|
||||
@@ -3,29 +3,13 @@
|
||||
name: species-name-human
|
||||
roundStart: false
|
||||
prototype: MobGingerbread
|
||||
sprites: MobGingerbreadSprites
|
||||
bodyTypes:
|
||||
- GingerbreadNormal
|
||||
markingLimits: MobHumanMarkingLimits
|
||||
dollPrototype: MobGingerbreadDummy
|
||||
skinColoration: HumanToned
|
||||
defaultSkinTone: "#9a7c5a"
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobGingerbreadSprites
|
||||
sprites:
|
||||
Head: MobGingerbreadHead
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Chest: MobGingerbreadTorso
|
||||
Eyes: MobGingerbreadEyes
|
||||
LArm: MobGingerbreadLArm
|
||||
RArm: MobGingerbreadRArm
|
||||
LHand: MobGingerbreadLHand
|
||||
RHand: MobGingerbreadRHand
|
||||
LLeg: MobGingerbreadLLeg
|
||||
RLeg: MobGingerbreadRLeg
|
||||
LFoot: MobGingerbreadLFoot
|
||||
RFoot: MobGingerbreadRFoot
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobGingerbreadEyes
|
||||
baseSprite:
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
name: species-name-human
|
||||
roundStart: true
|
||||
prototype: MobHuman
|
||||
sprites: MobHumanSprites
|
||||
bodyTypes:
|
||||
- HumanNormal
|
||||
- HumanSlim
|
||||
markingLimits: MobHumanMarkingLimits
|
||||
dollPrototype: MobHumanDummy
|
||||
skinColoration: HumanToned
|
||||
@@ -14,24 +16,6 @@
|
||||
# be defined as a 'custom base layer'
|
||||
# in either the mob's starting marking prototype,
|
||||
# or it has to be added in C#.
|
||||
- type: speciesBaseSprites
|
||||
id: MobHumanSprites
|
||||
sprites:
|
||||
Head: MobHumanHead
|
||||
Hair: MobHumanoidAnyMarking
|
||||
FacialHair: MobHumanoidAnyMarking
|
||||
Chest: MobHumanTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobHumanLArm
|
||||
RArm: MobHumanRArm
|
||||
LHand: MobHumanLHand
|
||||
RHand: MobHumanRHand
|
||||
LLeg: MobHumanLLeg
|
||||
RLeg: MobHumanRLeg
|
||||
LFoot: MobHumanLFoot
|
||||
RFoot: MobHumanRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobHumanMarkingLimits
|
||||
@@ -71,17 +55,12 @@
|
||||
id: MobHumanoidMarkingMatchSkin
|
||||
markingsMatchSkin: true
|
||||
|
||||
# Normal body type sprites
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanHead
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: head_m
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanHeadMale
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: head_m
|
||||
state: head
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanHeadFemale
|
||||
@@ -93,13 +72,7 @@
|
||||
id: MobHumanTorso
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanTorsoMale
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
state: torso
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanTorsoFemale
|
||||
@@ -154,3 +127,77 @@
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: r_foot
|
||||
|
||||
# Slim types
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimHead
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: head_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimHeadFemale
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: head_slim_f
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimTorso
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimTorsoFemale
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_slim_f
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimLLeg
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: l_leg_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimLArm
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: l_arm_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimLHand
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: l_hand_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimLFoot
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: l_foot_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimRLeg
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: r_leg_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimRArm
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: r_arm_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimRHand
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: r_hand_slim
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobHumanSlimRFoot
|
||||
baseSprite:
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: r_foot_slim
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-moth
|
||||
roundStart: true
|
||||
prototype: MobMoth
|
||||
sprites: MobMothSprites
|
||||
bodyTypes:
|
||||
- MothNormal
|
||||
defaultSkinTone: "#ffda93"
|
||||
markingLimits: MobMothMarkingLimits
|
||||
dollPrototype: MobMothDummy
|
||||
@@ -12,25 +13,6 @@
|
||||
femaleFirstNames: names_moth_first_female
|
||||
lastNames: names_moth_last
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobMothSprites
|
||||
sprites:
|
||||
Head: MobMothHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobMothTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobMothEyes
|
||||
LArm: MobMothLArm
|
||||
RArm: MobMothRArm
|
||||
LHand: MobMothLHand
|
||||
RHand: MobMothRHand
|
||||
LLeg: MobMothLLeg
|
||||
RLeg: MobMothRLeg
|
||||
LFoot: MobMothLFoot
|
||||
RFoot: MobMothRFoot
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobMothEyes
|
||||
baseSprite:
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-reptilian
|
||||
roundStart: true
|
||||
prototype: MobReptilian
|
||||
sprites: MobReptilianSprites
|
||||
bodyTypes:
|
||||
- ReptilianNormal
|
||||
defaultSkinTone: "#34a223"
|
||||
markingLimits: MobReptilianMarkingLimits
|
||||
dollPrototype: MobReptilianDummy
|
||||
@@ -12,24 +13,6 @@
|
||||
femaleFirstNames: names_reptilian_female
|
||||
naming: FirstDashFirst
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobReptilianSprites
|
||||
sprites:
|
||||
Head: MobReptilianHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobReptilianTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobReptilianLArm
|
||||
RArm: MobReptilianRArm
|
||||
LHand: MobReptilianLHand
|
||||
RHand: MobReptilianRHand
|
||||
LLeg: MobReptilianLLeg
|
||||
RLeg: MobReptilianRLeg
|
||||
LFoot: MobReptilianLFoot
|
||||
RFoot: MobReptilianRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobReptilianMarkingLimits
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-skeleton
|
||||
roundStart: false
|
||||
prototype: MobSkeletonPerson
|
||||
sprites: MobSkeletonSprites
|
||||
bodyTypes:
|
||||
- SkeletonNormal
|
||||
defaultSkinTone: "#fff9e2"
|
||||
markingLimits: MobHumanMarkingLimits
|
||||
maleFirstNames: skeletonNamesFirst
|
||||
@@ -11,20 +12,6 @@
|
||||
dollPrototype: MobSkeletonPersonDummy
|
||||
skinColoration: TintedHues
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobSkeletonSprites
|
||||
sprites:
|
||||
Head: MobSkeletonHead
|
||||
Chest: MobSkeletonTorso
|
||||
LArm: MobSkeletonLArm
|
||||
RArm: MobSkeletonRArm
|
||||
LHand: MobSkeletonLHand
|
||||
RHand: MobSkeletonRHand
|
||||
LLeg: MobSkeletonLLeg
|
||||
RLeg: MobSkeletonRLeg
|
||||
LFoot: MobSkeletonLFoot
|
||||
RFoot: MobSkeletonRFoot
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobSkeletonHead
|
||||
baseSprite:
|
||||
|
||||
@@ -3,29 +3,13 @@
|
||||
name: species-name-slime
|
||||
roundStart: true
|
||||
prototype: MobSlimePerson
|
||||
sprites: MobSlimeSprites
|
||||
bodyTypes:
|
||||
- SlimeNormal
|
||||
defaultSkinTone: "#b8b8b8"
|
||||
markingLimits: MobSlimeMarkingLimits
|
||||
dollPrototype: MobSlimePersonDummy
|
||||
skinColoration: Hues
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobSlimeSprites
|
||||
sprites:
|
||||
Head: MobSlimeHead
|
||||
Hair: MobSlimeMarkingFollowSkin
|
||||
FacialHair: MobSlimeMarkingFollowSkin
|
||||
Chest: MobSlimeTorso
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobSlimeLArm
|
||||
RArm: MobSlimeRArm
|
||||
LHand: MobSlimeLHand
|
||||
RHand: MobSlimeRHand
|
||||
LLeg: MobSlimeLLeg
|
||||
RLeg: MobSlimeRLeg
|
||||
LFoot: MobSlimeLFoot
|
||||
RFoot: MobSlimeRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobSlimeMarkingLimits
|
||||
points:
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: Terminator
|
||||
roundStart: false
|
||||
prototype: MobTerminatorEndoskeleton
|
||||
sprites: MobTerminatorSprites
|
||||
bodyTypes:
|
||||
- TerminatorNormal
|
||||
defaultSkinTone: "#fff9e2"
|
||||
markingLimits: MobHumanMarkingLimits
|
||||
maleFirstNames: skeletonNamesFirst
|
||||
@@ -11,19 +12,6 @@
|
||||
dollPrototype: MobSkeletonPersonDummy
|
||||
skinColoration: TintedHues
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobTerminatorSprites
|
||||
sprites:
|
||||
Head: MobTerminatorHead
|
||||
Chest: MobTerminatorTorso
|
||||
LArm: MobTerminatorLArm
|
||||
RArm: MobTerminatorRArm
|
||||
LHand: MobTerminatorLHand
|
||||
RHand: MobTerminatorRHand
|
||||
LLeg: MobTerminatorLLeg
|
||||
RLeg: MobTerminatorRLeg
|
||||
LFoot: MobTerminatorLFoot
|
||||
RFoot: MobTerminatorRFoot
|
||||
|
||||
- type: humanoidBaseSprite
|
||||
id: MobTerminatorHead
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
name: species-name-vox
|
||||
roundStart: false # sad...
|
||||
prototype: MobVox
|
||||
sprites: MobVoxSprites
|
||||
bodyTypes:
|
||||
- VoxNormal
|
||||
markingLimits: MobVoxMarkingLimits
|
||||
dollPrototype: MobVoxDummy
|
||||
skinColoration: Hues
|
||||
@@ -14,23 +15,6 @@
|
||||
- Unsexed
|
||||
|
||||
|
||||
- type: speciesBaseSprites
|
||||
id: MobVoxSprites
|
||||
sprites:
|
||||
Head: MobVoxHead
|
||||
Hair: MobHumanoidAnyMarking
|
||||
FacialHair: MobHumanoidAnyMarking
|
||||
Chest: MobVoxTorso
|
||||
Eyes: MobVoxEyes
|
||||
LArm: MobVoxLArm
|
||||
RArm: MobVoxRArm
|
||||
LHand: MobVoxLHand
|
||||
RHand: MobVoxRHand
|
||||
LLeg: MobVoxLLeg
|
||||
RLeg: MobVoxRLeg
|
||||
LFoot: MobVoxLFoot
|
||||
RFoot: MobVoxRFoot
|
||||
|
||||
- type: markingPoints
|
||||
id: MobVoxMarkingLimits
|
||||
onlyWhitelisted: true
|
||||
|
||||
180
Resources/Prototypes/_White/BodyTypes/normal.yml
Normal file
@@ -0,0 +1,180 @@
|
||||
- type: bodyType
|
||||
id: HumanNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobHumanHead
|
||||
Hair: MobHumanoidAnyMarking
|
||||
FacialHair: MobHumanoidAnyMarking
|
||||
Chest: MobHumanTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobHumanLArm
|
||||
RArm: MobHumanRArm
|
||||
LHand: MobHumanLHand
|
||||
RHand: MobHumanRHand
|
||||
LLeg: MobHumanLLeg
|
||||
RLeg: MobHumanRLeg
|
||||
LFoot: MobHumanLFoot
|
||||
RFoot: MobHumanRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: ReptilianNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobReptilianHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobReptilianTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobReptilianLArm
|
||||
RArm: MobReptilianRArm
|
||||
LHand: MobReptilianLHand
|
||||
RHand: MobReptilianRHand
|
||||
LLeg: MobReptilianLLeg
|
||||
RLeg: MobReptilianRLeg
|
||||
LFoot: MobReptilianLFoot
|
||||
RFoot: MobReptilianRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: SkeletonNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobSkeletonHead
|
||||
Chest: MobSkeletonTorso
|
||||
LArm: MobSkeletonLArm
|
||||
RArm: MobSkeletonRArm
|
||||
LHand: MobSkeletonLHand
|
||||
RHand: MobSkeletonRHand
|
||||
LLeg: MobSkeletonLLeg
|
||||
RLeg: MobSkeletonRLeg
|
||||
LFoot: MobSkeletonLFoot
|
||||
RFoot: MobSkeletonRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: SlimeNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobSlimeHead
|
||||
Hair: MobSlimeMarkingFollowSkin
|
||||
FacialHair: MobSlimeMarkingFollowSkin
|
||||
Chest: MobSlimeTorso
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobSlimeLArm
|
||||
RArm: MobSlimeRArm
|
||||
LHand: MobSlimeLHand
|
||||
RHand: MobSlimeRHand
|
||||
LLeg: MobSlimeLLeg
|
||||
RLeg: MobSlimeRLeg
|
||||
LFoot: MobSlimeLFoot
|
||||
RFoot: MobSlimeRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: VoxNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobVoxHead
|
||||
Hair: MobHumanoidAnyMarking
|
||||
FacialHair: MobHumanoidAnyMarking
|
||||
Chest: MobVoxTorso
|
||||
Eyes: MobVoxEyes
|
||||
LArm: MobVoxLArm
|
||||
RArm: MobVoxRArm
|
||||
LHand: MobVoxLHand
|
||||
RHand: MobVoxRHand
|
||||
LLeg: MobVoxLLeg
|
||||
RLeg: MobVoxRLeg
|
||||
LFoot: MobVoxLFoot
|
||||
RFoot: MobVoxRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: DionaNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobDionaHead
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Chest: MobDionaTorso
|
||||
LArm: MobDionaLArm
|
||||
RArm: MobDionaRArm
|
||||
LHand: MobDionaLHand
|
||||
RHand: MobDionaRHand
|
||||
LLeg: MobDionaLLeg
|
||||
RLeg: MobDionaRLeg
|
||||
LFoot: MobDionaLFoot
|
||||
RFoot: MobDionaRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: ArachnidNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobArachnidHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobArachnidTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobArachnidEyes
|
||||
LArm: MobArachnidLArm
|
||||
RArm: MobArachnidRArm
|
||||
LHand: MobArachnidLHand
|
||||
RHand: MobArachnidRHand
|
||||
LLeg: MobArachnidLLeg
|
||||
RLeg: MobArachnidRLeg
|
||||
LFoot: MobArachnidLFoot
|
||||
RFoot: MobArachnidRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: TerminatorNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobTerminatorHead
|
||||
Chest: MobTerminatorTorso
|
||||
LArm: MobTerminatorLArm
|
||||
RArm: MobTerminatorRArm
|
||||
LHand: MobTerminatorLHand
|
||||
RHand: MobTerminatorRHand
|
||||
LLeg: MobTerminatorLLeg
|
||||
RLeg: MobTerminatorRLeg
|
||||
LFoot: MobTerminatorLFoot
|
||||
RFoot: MobTerminatorRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: GingerbreadNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobGingerbreadHead
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Chest: MobGingerbreadTorso
|
||||
Eyes: MobGingerbreadEyes
|
||||
LArm: MobGingerbreadLArm
|
||||
RArm: MobGingerbreadRArm
|
||||
LHand: MobGingerbreadLHand
|
||||
RHand: MobGingerbreadRHand
|
||||
LLeg: MobGingerbreadLLeg
|
||||
RLeg: MobGingerbreadRLeg
|
||||
LFoot: MobGingerbreadLFoot
|
||||
RFoot: MobGingerbreadRFoot
|
||||
|
||||
- type: bodyType
|
||||
id: MothNormal
|
||||
name: body-normal
|
||||
sprites:
|
||||
Head: MobMothHead
|
||||
Snout: MobHumanoidAnyMarking
|
||||
Chest: MobMothTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
HeadSide: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobMothEyes
|
||||
LArm: MobMothLArm
|
||||
RArm: MobMothRArm
|
||||
LHand: MobMothLHand
|
||||
RHand: MobMothRHand
|
||||
LLeg: MobMothLLeg
|
||||
RLeg: MobMothRLeg
|
||||
LFoot: MobMothLFoot
|
||||
RFoot: MobMothRFoot
|
||||
43
Resources/Prototypes/_White/BodyTypes/slim.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
- type: bodyType
|
||||
id: HumanSlim
|
||||
name: body-slim
|
||||
sexRestrictions:
|
||||
- Male
|
||||
sprites:
|
||||
Head: MobHumanSlimHead
|
||||
Hair: MobHumanoidAnyMarking
|
||||
FacialHair: MobHumanoidAnyMarking
|
||||
Chest: MobHumanSlimTorso
|
||||
HeadTop: MobHumanoidAnyMarking
|
||||
Tail: MobHumanoidAnyMarking
|
||||
Eyes: MobHumanoidEyes
|
||||
LArm: MobHumanSlimLArm
|
||||
RArm: MobHumanSlimRArm
|
||||
LHand: MobHumanSlimLHand
|
||||
RHand: MobHumanSlimRHand
|
||||
LLeg: MobHumanSlimLLeg
|
||||
RLeg: MobHumanSlimRLeg
|
||||
LFoot: MobHumanSlimLFoot
|
||||
RFoot: MobHumanSlimRFoot
|
||||
|
||||
# - type: bodyType
|
||||
# id: ReptilianSlim
|
||||
# name: body-slim
|
||||
# sexRestrictions:
|
||||
# - Male
|
||||
# sprites:
|
||||
# Head: MobReptilianSlimHead
|
||||
# Snout: MobHumanoidAnyMarking
|
||||
# Chest: MobReptilianSlimTorso
|
||||
# HeadTop: MobHumanoidAnyMarking
|
||||
# HeadSide: MobHumanoidAnyMarking
|
||||
# Tail: MobHumanoidAnyMarking
|
||||
# Eyes: MobHumanoidEyes
|
||||
# LArm: MobReptilianSlimLArm
|
||||
# RArm: MobReptilianSlimRArm
|
||||
# LHand: MobReptilianSlimLHand
|
||||
# RHand: MobReptilianSlimRHand
|
||||
# LLeg: MobReptilianSlimLLeg
|
||||
# RLeg: MobReptilianSlimRLeg
|
||||
# LFoot: MobReptilianSlimLFoot
|
||||
# RFoot: MobReptilianSlimRFoot
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-kangaroo",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-kangaroo",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-kangaroo",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-kangaroo",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1 +1,35 @@
|
||||
{"version": 1, "license": "CC-BY-SA-3.0", "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/4f6190e2895e09116663ef282d3ce1d8b35c032e", "size": {"x": 32, "y": 32}, "states": [{"name": "icon"}, {"name": "equipped-HAND", "directions": 4}, {"name": "inhand-left", "directions": 4}, {"name": "inhand-right", "directions": 4}, {"name": "equipped-HAND-vox", "directions": 4}]}
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/4f6190e2895e09116663ef282d3ce1d8b35c032e",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-vox",
|
||||
"directions": 4,
|
||||
"delays": [[1.0], [1.0], [1.0], [1.0]]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -17,10 +17,18 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "on-equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "on-equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -28,6 +28,18 @@
|
||||
"name": "green-equipped-HAND",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "red-equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "green-equipped-HAND-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-OUTERCLOTHING",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-OUTERCLOTHING-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||
|
After Width: | Height: | Size: 834 B |
@@ -14,6 +14,10 @@
|
||||
"name": "equipped-OUTERCLOTHING",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-OUTERCLOTHING-body-slim",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
|
||||