Added hair, facial hair, magic mirror (#452)
* Added hair, facial hair, magic mirror * I forgot to commit the textures lmao * Use shader to fix hair color blending
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.Preferences.Appearance;
|
||||
using Robust.Client.GameObjects.Components.UserInterface;
|
||||
using Robust.Client.Interfaces.ResourceManagement;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.GameObjects.Components.Renderable;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.GameObjects.Components
|
||||
{
|
||||
public class MagicMirrorBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IResourceCache _resourceCache;
|
||||
[Dependency] private readonly ILocalizationManager _localization;
|
||||
#pragma warning restore 649
|
||||
private MagicMirrorWindow _window;
|
||||
|
||||
public MagicMirrorBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = new MagicMirrorWindow(this,_resourceCache, _localization);
|
||||
_window.OnClose += Close;
|
||||
_window.Open();
|
||||
}
|
||||
|
||||
internal void HairSelected(string name, bool isFacialHair)
|
||||
{
|
||||
SendMessage(new SharedMagicMirrorComponent.HairSelectedMessage(name, isFacialHair));
|
||||
}
|
||||
|
||||
internal void HairColorSelected(Color color, bool isFacialHair)
|
||||
{
|
||||
SendMessage(new SharedMagicMirrorComponent.HairColorSelectedMessage(color, isFacialHair));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_window.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FacialHairPickerWindow : HairPickerWindow
|
||||
{
|
||||
public FacialHairPickerWindow(IResourceCache resourceCache, ILocalizationManager localization) : base(resourceCache, localization)
|
||||
{
|
||||
Title = "Facial hair";
|
||||
}
|
||||
|
||||
public override void Populate()
|
||||
{
|
||||
var humanFacialHairRSIPath = SharedSpriteComponent.TextureRoot / "Mob/human_facial_hair.rsi";
|
||||
var humanFacialHairRSI = ResourceCache.GetResource<RSIResource>(humanFacialHairRSIPath).RSI;
|
||||
foreach (var (styleName, styleState) in HairStyles.FacialHairStylesMap)
|
||||
{
|
||||
Items.AddItem(styleName, humanFacialHairRSI[styleState].Frame0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HairPickerWindow : SS14Window
|
||||
{
|
||||
public event Action<Color> OnHairColorPicked;
|
||||
public event Action<string> OnHairStylePicked;
|
||||
|
||||
protected readonly IResourceCache ResourceCache;
|
||||
protected readonly ItemList Items;
|
||||
protected override Vector2? CustomSize => (300, 300);
|
||||
public HairPickerWindow(IResourceCache resourceCache, ILocalizationManager localization)
|
||||
{
|
||||
Title = "Hair";
|
||||
ResourceCache = resourceCache;
|
||||
var vBox = new VBoxContainer();
|
||||
Contents.AddChild(vBox);
|
||||
|
||||
var colorHBox = new HBoxContainer();
|
||||
vBox.AddChild(colorHBox);
|
||||
|
||||
var colorLabel = new Label
|
||||
{
|
||||
Text = localization.GetString("Color: ")
|
||||
};
|
||||
colorHBox.AddChild(colorLabel);
|
||||
|
||||
var colorEdit = new LineEdit
|
||||
{
|
||||
SizeFlagsHorizontal = SizeFlags.FillExpand
|
||||
};
|
||||
colorEdit.OnTextChanged += args =>
|
||||
{
|
||||
var color = Color.TryFromHex(args.Text);
|
||||
if (color.HasValue)
|
||||
{
|
||||
OnHairColorPicked?.Invoke(color.Value);
|
||||
}
|
||||
};
|
||||
colorHBox.AddChild(colorEdit);
|
||||
|
||||
Items = new ItemList
|
||||
{
|
||||
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||
};
|
||||
vBox.AddChild(Items);
|
||||
Items.OnItemSelected += ItemSelected;
|
||||
}
|
||||
|
||||
public virtual void Populate()
|
||||
{
|
||||
var humanHairRSIPath = SharedSpriteComponent.TextureRoot / "Mob/human_hair.rsi";
|
||||
var humanHairRSI = ResourceCache.GetResource<RSIResource>(humanHairRSIPath).RSI;
|
||||
foreach (var (styleName, styleState) in HairStyles.HairStylesMap)
|
||||
{
|
||||
Items.AddItem(styleName, humanHairRSI[styleState].Frame0);
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemSelected(ItemList.ItemListSelectedEventArgs args)
|
||||
{
|
||||
OnHairStylePicked?.Invoke(Items[args.ItemIndex].Text);
|
||||
}
|
||||
}
|
||||
|
||||
public class MagicMirrorWindow : SS14Window
|
||||
{
|
||||
private readonly HairPickerWindow _hairPickerWindow;
|
||||
private readonly FacialHairPickerWindow _facialHairPickerWindow;
|
||||
|
||||
public MagicMirrorWindow(MagicMirrorBoundUserInterface owner, IResourceCache resourceCache, ILocalizationManager localization)
|
||||
{
|
||||
Title = "Magic Mirror";
|
||||
|
||||
_hairPickerWindow = new HairPickerWindow(resourceCache, localization);
|
||||
_hairPickerWindow.Populate();
|
||||
_hairPickerWindow.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, false);
|
||||
_hairPickerWindow.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, false);
|
||||
|
||||
_facialHairPickerWindow = new FacialHairPickerWindow(resourceCache, localization);
|
||||
_facialHairPickerWindow.Populate();
|
||||
_facialHairPickerWindow.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, true);
|
||||
_facialHairPickerWindow.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, true);
|
||||
|
||||
var vBox = new VBoxContainer();
|
||||
Contents.AddChild(vBox);
|
||||
|
||||
var hairButton = new Button
|
||||
{
|
||||
Text = localization.GetString("Customize hair")
|
||||
};
|
||||
hairButton.OnPressed += args => _hairPickerWindow.Open();
|
||||
vBox.AddChild(hairButton);
|
||||
|
||||
var facialHairButton = new Button
|
||||
{
|
||||
Text = localization.GetString("Customize facial hair")
|
||||
};
|
||||
facialHairButton.OnPressed += args => _facialHairPickerWindow.Open();
|
||||
vBox.AddChild(facialHairButton);
|
||||
|
||||
Size = CombinedMinimumSize;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_hairPickerWindow.Dispose();
|
||||
_facialHairPickerWindow.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
Content.Client/GameObjects/Components/Mobs/HairComponent.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.Preferences.Appearance;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics.Shaders;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class HairComponent : SharedHairComponent
|
||||
{
|
||||
private const string HairShaderName = "hair";
|
||||
private const string HairColorParameter = "hairColor";
|
||||
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
private ShaderInstance _facialHairShader;
|
||||
private ShaderInstance _hairShader;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
var shaderProto = _prototypeManager.Index<ShaderPrototype>(HairShaderName);
|
||||
|
||||
_facialHairShader = shaderProto.InstanceUnique();
|
||||
_hairShader = shaderProto.InstanceUnique();
|
||||
}
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
if (Owner.TryGetComponent(out ISpriteComponent sprite))
|
||||
{
|
||||
sprite.LayerSetShader(HumanoidVisualLayers.Hair, _hairShader);
|
||||
sprite.LayerSetShader(HumanoidVisualLayers.FacialHair, _facialHairShader);
|
||||
}
|
||||
}
|
||||
|
||||
public override string FacialHairStyleName
|
||||
{
|
||||
get => base.FacialHairStyleName;
|
||||
set
|
||||
{
|
||||
base.FacialHairStyleName = value;
|
||||
UpdateHairStyle();
|
||||
}
|
||||
}
|
||||
|
||||
public override string HairStyleName
|
||||
{
|
||||
get => base.HairStyleName;
|
||||
set
|
||||
{
|
||||
base.HairStyleName = value;
|
||||
UpdateHairStyle();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color HairColor
|
||||
{
|
||||
get => base.HairColor;
|
||||
set
|
||||
{
|
||||
base.HairColor = value;
|
||||
UpdateHairStyle();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color FacialHairColor
|
||||
{
|
||||
get => base.FacialHairColor;
|
||||
set
|
||||
{
|
||||
base.FacialHairColor = value;
|
||||
UpdateHairStyle();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHairStyle()
|
||||
{
|
||||
var sprite = Owner.GetComponent<SpriteComponent>();
|
||||
|
||||
_hairShader?.SetParameter(HairColorParameter, HairColor);
|
||||
_facialHairShader?.SetParameter(HairColorParameter, FacialHairColor);
|
||||
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Hair,
|
||||
HairStyles.HairStylesMap[HairStyleName ?? HairStyles.DefaultHairStyle]);
|
||||
sprite.LayerSetState(HumanoidVisualLayers.FacialHair,
|
||||
HairStyles.FacialHairStylesMap[FacialHairStyleName ?? HairStyles.DefaultFacialHairStyle]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.Preferences.Appearance;
|
||||
using Robust.Server.GameObjects.Components.UserInterface;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameObjects.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class MagicMirrorComponent : SharedMagicMirrorComponent, IActivate
|
||||
{
|
||||
private BoundUserInterface _userInterface;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(MagicMirrorUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||
}
|
||||
|
||||
private static void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||
{
|
||||
var hair = obj.Session.AttachedEntity.GetComponent<HairComponent>();
|
||||
switch (obj.Message)
|
||||
{
|
||||
case HairSelectedMessage msg:
|
||||
var map =
|
||||
msg.IsFacialHair ? HairStyles.FacialHairStylesMap : HairStyles.HairStylesMap;
|
||||
if (!map.ContainsKey(msg.HairName))
|
||||
return;
|
||||
|
||||
if (msg.IsFacialHair)
|
||||
{
|
||||
hair.FacialHairStyleName = msg.HairName;
|
||||
}
|
||||
else
|
||||
{
|
||||
hair.HairStyleName = msg.HairName;
|
||||
}
|
||||
|
||||
break;
|
||||
case HairColorSelectedMessage msg:
|
||||
if (msg.IsFacialHair)
|
||||
{
|
||||
hair.FacialHairColor = msg.HairColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
hair.HairColor = msg.HairColor;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.User.TryGetComponent(out IActorComponent actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_userInterface.Open(actor.playerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Content.Server/GameObjects/Components/Mobs/HairComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class HairComponent : SharedHairComponent
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Mobs
|
||||
{
|
||||
public abstract class SharedHairComponent : Component
|
||||
{
|
||||
private string _facialHairStyleName;
|
||||
private string _hairStyleName;
|
||||
private Color _hairColor;
|
||||
private Color _facialHairColor;
|
||||
|
||||
public sealed override string Name => "Hair";
|
||||
public sealed override uint? NetID => ContentNetIDs.HAIR;
|
||||
public sealed override Type StateType => typeof(HairComponentState);
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual string HairStyleName
|
||||
{
|
||||
get => _hairStyleName;
|
||||
set
|
||||
{
|
||||
_hairStyleName = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual string FacialHairStyleName
|
||||
{
|
||||
get => _facialHairStyleName;
|
||||
set
|
||||
{
|
||||
_facialHairStyleName = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual Color HairColor
|
||||
{
|
||||
get => _hairColor;
|
||||
set
|
||||
{
|
||||
_hairColor = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual Color FacialHairColor
|
||||
{
|
||||
get => _facialHairColor;
|
||||
set
|
||||
{
|
||||
_facialHairColor = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new HairComponentState(HairStyleName, FacialHairStyleName, HairColor, FacialHairColor);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
var cast = (HairComponentState) curState;
|
||||
|
||||
HairStyleName = cast.HairStyleName;
|
||||
FacialHairStyleName = cast.FacialHairStyleName;
|
||||
HairColor = cast.HairColor;
|
||||
FacialHairColor = cast.FacialHairColor;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
private sealed class HairComponentState : ComponentState
|
||||
{
|
||||
public string HairStyleName { get; }
|
||||
public string FacialHairStyleName { get; }
|
||||
public Color HairColor { get; }
|
||||
public Color FacialHairColor { get; }
|
||||
|
||||
public HairComponentState(string hairStyleName, string facialHairStyleName, Color hairColor, Color facialHairColor) : base(ContentNetIDs.HAIR)
|
||||
{
|
||||
HairStyleName = hairStyleName;
|
||||
FacialHairStyleName = facialHairStyleName;
|
||||
HairColor = hairColor;
|
||||
FacialHairColor = facialHairColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components
|
||||
{
|
||||
public class SharedMagicMirrorComponent : Component
|
||||
{
|
||||
public override string Name => "MagicMirror";
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum MagicMirrorUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class HairSelectedMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string HairName;
|
||||
public readonly bool IsFacialHair;
|
||||
|
||||
public HairSelectedMessage(string name, bool isFacialHair)
|
||||
{
|
||||
HairName = name;
|
||||
IsFacialHair = isFacialHair;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class HairColorSelectedMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly Color HairColor;
|
||||
public readonly bool IsFacialHair;
|
||||
|
||||
public HairColorSelectedMessage(Color color, bool isFacialHair)
|
||||
{
|
||||
HairColor = color;
|
||||
IsFacialHair = isFacialHair;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,5 +34,6 @@
|
||||
public const uint ITEMCOOLDOWN = 1029;
|
||||
public const uint CARGO_ORDER_DATABASE = 1030;
|
||||
public const uint GALACTIC_MARKET = 1031;
|
||||
public const uint HAIR = 1032;
|
||||
}
|
||||
}
|
||||
|
||||
192
Content.Shared/Preferences/Appearance/HairStyles.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Shared.Preferences.Appearance
|
||||
{
|
||||
public static class HairStyles
|
||||
{
|
||||
public const string DefaultHairStyle = "Bald";
|
||||
public const string DefaultFacialHairStyle = "Shaved";
|
||||
|
||||
public static readonly Dictionary<string, string> HairStylesMap = new Dictionary<string, string>
|
||||
{
|
||||
{"Bald", "bald"},
|
||||
{"Afro", "afro"},
|
||||
{"Big Afro", "bigafro"},
|
||||
{"Afro 2", "afro2"},
|
||||
{"Asymmetrical Bob", "asymmbob"},
|
||||
{"Balding Hair", "balding"},
|
||||
{"Bedhead", "bedhead"},
|
||||
{"Bedhead 2", "bedheadv2"},
|
||||
{"Bedhead 3", "bedheadv3"},
|
||||
{"Beehive", "beehive"},
|
||||
{"Beehive 2", "beehive2"},
|
||||
{"Birdnest", "birdnest"},
|
||||
{"Birdnest 2", "birdnest2"},
|
||||
{"Mercenary", "blackswordsman"},
|
||||
{"Bob", "bobcut"},
|
||||
{"Bobcurl", "bobcurl"},
|
||||
{"Bowl 1", "bowlcut1"},
|
||||
{"Bowl 2", "bowlcut2"},
|
||||
{"Floorlength Braid", "braid"},
|
||||
{"Long Braid", "hbraid"},
|
||||
{"Business Hair", "business"},
|
||||
{"Business Hair 2", "business2"},
|
||||
{"Business Hair 3", "business3"},
|
||||
{"Business Hair 4", "business4"},
|
||||
{"Bun", "bun"},
|
||||
{"Casual Bun", "bunalt"},
|
||||
{"Bun 2", "bun2"},
|
||||
{"Bun 3", "bun3"},
|
||||
{"Buzzcut", "buzzcut"},
|
||||
{"Chop", "chop"},
|
||||
{"CIA", "cia"},
|
||||
{"Combover", "combover"},
|
||||
{"Coffee House", "coffeehouse"},
|
||||
{"Crewcut", "crewcut"},
|
||||
{"Chrono", "toriyama"},
|
||||
{"Curls", "curls"},
|
||||
{"Cut Hair", "cuthair"},
|
||||
{"Dandy Pompadour", "dandypompadour"},
|
||||
{"Devil Lock", "devilock"},
|
||||
{"Double-Bun", "doublebun"},
|
||||
{"Dreadlocks", "dreads"},
|
||||
{"80's", "80s"},
|
||||
{"Emo", "emo"},
|
||||
{"Flow Hair", "flowhair"},
|
||||
{"The Family Man", "thefamilyman"},
|
||||
{"Father", "father"},
|
||||
{"Feather", "feather"},
|
||||
{"Cut Hair Alt", "femc"},
|
||||
{"Flaired Hair", "flair"},
|
||||
{"Emo Fringe", "emofringe"},
|
||||
{"Fringetail", "fringetail"},
|
||||
{"Gelled Back", "gelled"},
|
||||
{"Gentle", "gentle"},
|
||||
{"Half-banged Hair", "halfbang"},
|
||||
{"Half-banged Hair Alt", "halfbang_alt"},
|
||||
{"Half-Shaved", "halfshaved"},
|
||||
{"Half-Shaved Emo", "halfshaved_emo"},
|
||||
{"Hamaski Hair", "hamasaki"},
|
||||
{"Combed Hair", "hbangs"},
|
||||
{"Combed Hair Alt", "hbangs_alt"},
|
||||
{"High Ponytail", "highponytail"},
|
||||
{"Hime Cut", "himecut"},
|
||||
{"Hime Cut Alt", "himecut_alt"},
|
||||
{"Hitop", "hitop"},
|
||||
{"Adam Jensen Hair", "jensen"},
|
||||
{"Joestar", "joestar"},
|
||||
{"Pigtails", "kagami"},
|
||||
{"Kare", "kare"},
|
||||
{"Kusanagi Hair", "kusanagi"},
|
||||
{"Ladylike", "ladylike"},
|
||||
{"Ladylike alt", "ladylike2"},
|
||||
{"Long Emo", "emolong"},
|
||||
{"Long Hair", "vlong"},
|
||||
{"Long Hair Alt", "longeralt2"},
|
||||
{"Very Long Hair", "longest"},
|
||||
{"Longer Fringe", "vlongfringe"},
|
||||
{"Long Fringe", "longfringe"},
|
||||
{"Overeye Long", "longovereye"},
|
||||
{"Man Bun", "manbun"},
|
||||
{"Drillruru", "drillruru"},
|
||||
{"Medium Braid", "shortbraid"},
|
||||
{"Medium Braid Alt", "mediumbraid"},
|
||||
{"Messy Bun", "messybun"},
|
||||
{"Modern", "modern"},
|
||||
{"Mohawk", "mohawk"},
|
||||
{"Mulder", "mulder"},
|
||||
{"Nia", "nia"},
|
||||
{"Nitori", "nitori"},
|
||||
{"Odango", "odango"},
|
||||
{"Ombre", "ombre"},
|
||||
{"Oxton", "oxton"},
|
||||
{"Parted", "parted"},
|
||||
{"Pixie", "pixie"},
|
||||
{"Pompadour", "pompadour"},
|
||||
{"Ponytail 1", "ponytail"},
|
||||
{"Ponytail 2", "ponytail2"},
|
||||
{"Ponytail 3", "ponytail3"},
|
||||
{"Ponytail 4", "ponytail4"},
|
||||
{"Ponytail 5", "ponytail5"},
|
||||
{"Ponytail 6", "ponytail6"},
|
||||
{"Ponytail 7", "ponytail7"},
|
||||
{"Poofy", "poofy"},
|
||||
{"Poofy Alt", "poofy2"},
|
||||
{"Quiff", "quiff"},
|
||||
{"Ramona", "ramona"},
|
||||
{"Reverse Mohawk", "reversemohawk"},
|
||||
{"Ronin", "ronin"},
|
||||
{"Rows", "rows1"},
|
||||
{"Rows Alt", "rows2"},
|
||||
{"Rows Bun", "rows3"},
|
||||
{"Flat Top", "sargeant"},
|
||||
{"Scully", "scully"},
|
||||
{"Shaved Mohawk", "shavedmohawk"},
|
||||
{"Shaved Part", "shavedpart"},
|
||||
{"Short Hair", "short"},
|
||||
{"Short Hair 2", "short2"},
|
||||
{"Short Hair 3", "short3"},
|
||||
{"Short Bangs", "shortbangs"},
|
||||
{"Overeye Short", "shortovereye"},
|
||||
{"Shoulder-length Hair", "shoulderlen"},
|
||||
{"Sidepart Hair", "sidepart"},
|
||||
{"Side Ponytail", "stail"},
|
||||
{"One Shoulder", "oneshoulder"},
|
||||
{"Tress Shoulder", "tressshoulder"},
|
||||
{"Side Ponytail 2", "ponytailf"},
|
||||
{"Side Swipe", "sideswipe"},
|
||||
{"Skinhead", "skinhead"},
|
||||
{"Messy Hair", "smessy"},
|
||||
{"Sleeze", "sleeze"},
|
||||
{"Spiky", "spikey"},
|
||||
{"Stylo", "stylo"},
|
||||
{"Spiky Ponytail", "spikyponytail"},
|
||||
{"Top Knot", "topknot"},
|
||||
{"Thinning", "thinning"},
|
||||
{"Thinning Rear", "thinningrear"},
|
||||
{"Thinning Front", "thinningfront"},
|
||||
{"Undercut", "undercut"},
|
||||
{"Unkept", "unkept"},
|
||||
{"Updo", "updo"},
|
||||
{"Vegeta", "toriyama2"},
|
||||
{"Overeye Very Short", "veryshortovereye"},
|
||||
{"Overeye Very Short, Alternate", "veryshortovereyealternate"},
|
||||
{"Volaju", "volaju"},
|
||||
{"Wisp", "wisp"},
|
||||
{"Zieglertail", "ziegler"},
|
||||
{"Zone Braid", "zone"},
|
||||
};
|
||||
|
||||
public static readonly Dictionary<string, string> FacialHairStylesMap = new Dictionary<string, string>()
|
||||
{
|
||||
{"Shaved", "shaved"},
|
||||
{"Watson Mustache", "watson"},
|
||||
{"Hulk Hogan Mustache", "hogan"},
|
||||
{"Van Dyke Mustache", "vandyke"},
|
||||
{"Square Mustache", "chaplin"},
|
||||
{"Selleck Mustache", "selleck"},
|
||||
{"Neckbeard", "neckbeard"},
|
||||
{"Full Beard", "fullbeard"},
|
||||
{"Long Beard", "longbeard"},
|
||||
{"Very Long Beard", "wise"},
|
||||
{"Elvis Sideburns", "elvis"},
|
||||
{"Abraham Lincoln Beard", "abe"},
|
||||
{"Chinstrap", "chin"},
|
||||
{"Hipster Beard", "hip"},
|
||||
{"Goatee", "gt"},
|
||||
{"Adam Jensen Beard", "jensen"},
|
||||
{"Volaju", "volaju"},
|
||||
{"Dwarf Beard", "dwarf"},
|
||||
{"3 O'clock Shadow", "3oclock"},
|
||||
{"3 O'clock Shadow and Moustache", "3oclockmoustache"},
|
||||
{"5 O'clock Shadow", "5oclock"},
|
||||
{"5 O'clock Shadow and Moustache", "5oclockmoustache"},
|
||||
{"7 O'clock Shadow", "7oclock"},
|
||||
{"7 O'clock Shadow and Moustache", "7oclockmoustache"},
|
||||
{"Mutton Chops", "mutton"},
|
||||
{"Mutton Chops and Moustache", "muttonmu"},
|
||||
{"Walrus Moustache", "walrus"},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Preferences.Appearance
|
||||
{
|
||||
public enum HumanoidVisualLayers
|
||||
{
|
||||
Hair,
|
||||
FacialHair,
|
||||
}
|
||||
}
|
||||
26
Resources/Prototypes/Entities/buildings/mirror.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
- type: entity
|
||||
id: mirror
|
||||
name: Mirror
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Buildings/mirror.rsi
|
||||
state: mirror
|
||||
- type: Icon
|
||||
sprite: Buildings/mirror.rsi
|
||||
state: mirror
|
||||
- type: Collidable
|
||||
shapes:
|
||||
- !type:PhysShapeAabb
|
||||
mask: 19
|
||||
layer: 16
|
||||
- type: Clickable
|
||||
- type: Physics
|
||||
mass: 25
|
||||
Anchored: true
|
||||
- type: SnapGrid
|
||||
offset: Center
|
||||
- type: MagicMirror
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.MagicMirrorUiKey.Key
|
||||
type: MagicMirrorBoundUserInterface
|
||||
@@ -23,6 +23,12 @@
|
||||
layers:
|
||||
- sprite: Mob/human.rsi
|
||||
state: male
|
||||
- map: ["enum.HumanoidVisualLayers.Hair"]
|
||||
state: bald
|
||||
sprite: Mob/human_hair.rsi
|
||||
- map: ["enum.HumanoidVisualLayers.FacialHair"]
|
||||
state: shaved
|
||||
sprite: Mob/human_facial_hair.rsi
|
||||
- map: ["enum.Slots.INNERCLOTHING"]
|
||||
- map: ["enum.Slots.IDCARD"]
|
||||
- map: ["enum.Slots.SHOES"]
|
||||
@@ -75,4 +81,4 @@
|
||||
- type: Examiner
|
||||
- type: CharacterInfo
|
||||
- type: FootstepSound
|
||||
|
||||
- type: Hair
|
||||
|
||||
6
Resources/Prototypes/Shaders/hair.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
- type: shader
|
||||
id: hair
|
||||
kind: source
|
||||
path: "/Shaders/hair.swsl"
|
||||
params:
|
||||
hairColor: "#000000"
|
||||
8
Resources/Shaders/hair.swsl
Normal file
@@ -0,0 +1,8 @@
|
||||
// Additively blends the hair color onto the hair sprite.
|
||||
|
||||
uniform vec4 hairColor;
|
||||
|
||||
void fragment() {
|
||||
COLOR = texture(TEXTURE, UV);
|
||||
COLOR.rgb += hairColor.rgb;
|
||||
}
|
||||
1
Resources/Textures/Buildings/mirror.rsi/meta.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "mirror", "directions": 1, "delays": [[1.0]]}, {"name": "mirror_broke", "directions": 1, "delays": [[1.0]]}]}
|
||||
BIN
Resources/Textures/Buildings/mirror.rsi/mirror.png
Normal file
|
After Width: | Height: | Size: 279 B |
BIN
Resources/Textures/Buildings/mirror.rsi/mirror_broke.png
Normal file
|
After Width: | Height: | Size: 424 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/3oclock.png
Normal file
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 187 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/5oclock.png
Normal file
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 186 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/7oclock.png
Normal file
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 193 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/abe.png
Normal file
|
After Width: | Height: | Size: 178 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/chaplin.png
Normal file
|
After Width: | Height: | Size: 110 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/chin.png
Normal file
|
After Width: | Height: | Size: 130 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/dwarf.png
Normal file
|
After Width: | Height: | Size: 272 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/elvis.png
Normal file
|
After Width: | Height: | Size: 144 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/fullbeard.png
Normal file
|
After Width: | Height: | Size: 197 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/gt.png
Normal file
|
After Width: | Height: | Size: 170 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/hip.png
Normal file
|
After Width: | Height: | Size: 146 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/hogan.png
Normal file
|
After Width: | Height: | Size: 158 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/jensen.png
Normal file
|
After Width: | Height: | Size: 164 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/longbeard.png
Normal file
|
After Width: | Height: | Size: 226 B |
1
Resources/Textures/Mob/human_facial_hair.rsi/meta.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "3oclock", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "3oclockmoustache", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "5oclock", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "5oclockmoustache", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "7oclock", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "7oclockmoustache", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "abe", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "chaplin", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "chin", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "dwarf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "elvis", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "fullbeard", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "gt", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "hip", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "hogan", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "jensen", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "longbeard", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "mutton", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "muttonmu", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "neckbeard", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "selleck", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "shaved", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vandyke", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "volaju", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "walrus", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "watson", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "wise", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
|
||||
BIN
Resources/Textures/Mob/human_facial_hair.rsi/mutton.png
Normal file
|
After Width: | Height: | Size: 217 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/muttonmu.png
Normal file
|
After Width: | Height: | Size: 212 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/neckbeard.png
Normal file
|
After Width: | Height: | Size: 164 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/selleck.png
Normal file
|
After Width: | Height: | Size: 125 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/shaved.png
Normal file
|
After Width: | Height: | Size: 96 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/vandyke.png
Normal file
|
After Width: | Height: | Size: 146 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/volaju.png
Normal file
|
After Width: | Height: | Size: 179 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/walrus.png
Normal file
|
After Width: | Height: | Size: 160 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/watson.png
Normal file
|
After Width: | Height: | Size: 124 B |
BIN
Resources/Textures/Mob/human_facial_hair.rsi/wise.png
Normal file
|
After Width: | Height: | Size: 231 B |
BIN
Resources/Textures/Mob/human_hair.rsi/.png
Normal file
|
After Width: | Height: | Size: 153 B |
BIN
Resources/Textures/Mob/human_hair.rsi/80s.png
Normal file
|
After Width: | Height: | Size: 484 B |
BIN
Resources/Textures/Mob/human_hair.rsi/afro.png
Normal file
|
After Width: | Height: | Size: 527 B |
BIN
Resources/Textures/Mob/human_hair.rsi/afro2.png
Normal file
|
After Width: | Height: | Size: 306 B |
BIN
Resources/Textures/Mob/human_hair.rsi/asymmbob.png
Normal file
|
After Width: | Height: | Size: 519 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bald.png
Normal file
|
After Width: | Height: | Size: 96 B |
BIN
Resources/Textures/Mob/human_hair.rsi/balding.png
Normal file
|
After Width: | Height: | Size: 146 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bedhead.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bedheadv2.png
Normal file
|
After Width: | Height: | Size: 648 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bedheadv3.png
Normal file
|
After Width: | Height: | Size: 421 B |
BIN
Resources/Textures/Mob/human_hair.rsi/beehive.png
Normal file
|
After Width: | Height: | Size: 540 B |
BIN
Resources/Textures/Mob/human_hair.rsi/beehive2.png
Normal file
|
After Width: | Height: | Size: 487 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bigafro.png
Normal file
|
After Width: | Height: | Size: 832 B |
BIN
Resources/Textures/Mob/human_hair.rsi/birdnest.png
Normal file
|
After Width: | Height: | Size: 284 B |
BIN
Resources/Textures/Mob/human_hair.rsi/birdnest2.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
Resources/Textures/Mob/human_hair.rsi/blackswordsman.png
Normal file
|
After Width: | Height: | Size: 440 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bobcurl.png
Normal file
|
After Width: | Height: | Size: 396 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bobcut.png
Normal file
|
After Width: | Height: | Size: 278 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bowlcut1.png
Normal file
|
After Width: | Height: | Size: 171 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bowlcut2.png
Normal file
|
After Width: | Height: | Size: 301 B |
BIN
Resources/Textures/Mob/human_hair.rsi/braid.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bun.png
Normal file
|
After Width: | Height: | Size: 594 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bun2.png
Normal file
|
After Width: | Height: | Size: 567 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bun3.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
Resources/Textures/Mob/human_hair.rsi/bunalt.png
Normal file
|
After Width: | Height: | Size: 400 B |
BIN
Resources/Textures/Mob/human_hair.rsi/business.png
Normal file
|
After Width: | Height: | Size: 375 B |
BIN
Resources/Textures/Mob/human_hair.rsi/business2.png
Normal file
|
After Width: | Height: | Size: 560 B |
BIN
Resources/Textures/Mob/human_hair.rsi/business3.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
Resources/Textures/Mob/human_hair.rsi/business4.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
Resources/Textures/Mob/human_hair.rsi/buzzcut.png
Normal file
|
After Width: | Height: | Size: 239 B |
BIN
Resources/Textures/Mob/human_hair.rsi/chop.png
Normal file
|
After Width: | Height: | Size: 400 B |
BIN
Resources/Textures/Mob/human_hair.rsi/cia.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
Resources/Textures/Mob/human_hair.rsi/coffeehouse.png
Normal file
|
After Width: | Height: | Size: 379 B |
BIN
Resources/Textures/Mob/human_hair.rsi/combover.png
Normal file
|
After Width: | Height: | Size: 278 B |
BIN
Resources/Textures/Mob/human_hair.rsi/crewcut.png
Normal file
|
After Width: | Height: | Size: 216 B |
BIN
Resources/Textures/Mob/human_hair.rsi/curls.png
Normal file
|
After Width: | Height: | Size: 522 B |
BIN
Resources/Textures/Mob/human_hair.rsi/cuthair.png
Normal file
|
After Width: | Height: | Size: 349 B |
BIN
Resources/Textures/Mob/human_hair.rsi/dandypompadour.png
Normal file
|
After Width: | Height: | Size: 415 B |
BIN
Resources/Textures/Mob/human_hair.rsi/devilock.png
Normal file
|
After Width: | Height: | Size: 306 B |
BIN
Resources/Textures/Mob/human_hair.rsi/doublebun.png
Normal file
|
After Width: | Height: | Size: 447 B |
BIN
Resources/Textures/Mob/human_hair.rsi/dreads.png
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
Resources/Textures/Mob/human_hair.rsi/drillruru.png
Normal file
|
After Width: | Height: | Size: 643 B |
BIN
Resources/Textures/Mob/human_hair.rsi/emo.png
Normal file
|
After Width: | Height: | Size: 380 B |
BIN
Resources/Textures/Mob/human_hair.rsi/emofringe.png
Normal file
|
After Width: | Height: | Size: 404 B |
BIN
Resources/Textures/Mob/human_hair.rsi/emolong.png
Normal file
|
After Width: | Height: | Size: 481 B |
BIN
Resources/Textures/Mob/human_hair.rsi/father.png
Normal file
|
After Width: | Height: | Size: 295 B |
BIN
Resources/Textures/Mob/human_hair.rsi/feather.png
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
Resources/Textures/Mob/human_hair.rsi/femc.png
Normal file
|
After Width: | Height: | Size: 456 B |
BIN
Resources/Textures/Mob/human_hair.rsi/flair.png
Normal file
|
After Width: | Height: | Size: 451 B |
BIN
Resources/Textures/Mob/human_hair.rsi/flowhair.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
Resources/Textures/Mob/human_hair.rsi/fringetail.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
Resources/Textures/Mob/human_hair.rsi/gelled.png
Normal file
|
After Width: | Height: | Size: 232 B |
BIN
Resources/Textures/Mob/human_hair.rsi/gentle.png
Normal file
|
After Width: | Height: | Size: 363 B |
BIN
Resources/Textures/Mob/human_hair.rsi/halfbang.png
Normal file
|
After Width: | Height: | Size: 323 B |
BIN
Resources/Textures/Mob/human_hair.rsi/halfbang_alt.png
Normal file
|
After Width: | Height: | Size: 365 B |
BIN
Resources/Textures/Mob/human_hair.rsi/halfshaved.png
Normal file
|
After Width: | Height: | Size: 409 B |