* Import bird sprites and define basic mob.

* SKREEEEEEEEE

* Move hair styles to new sprite accessory prototypes.

Basic stuff, no multi-species stuff yet.

* Vox hair styles and clothes

* Make HumanoidCharacterProfile.Default() a static default to fix tests.

Usages that wanted the previous random behavior now call Random().

* Remove names from hair style prototypes.

(They're in localization files)

* Update Content.Shared/Actions/ActionType.cs

(sk)reeee github

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Pieter-Jan Briers
2021-03-28 08:26:32 +02:00
committed by GitHub
parent 5ed935f30a
commit 0ac4c0e85c
101 changed files with 2440 additions and 505 deletions

View File

@@ -61,7 +61,7 @@ namespace Content.Client.GameObjects.Components.Clothing
set => _femaleMask = value; set => _femaleMask = value;
} }
public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EquipmentSlotDefines.SlotFlags slot) public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EquipmentSlotDefines.SlotFlags slot, string? speciesId=null)
{ {
if (RsiPath == null) if (RsiPath == null)
{ {
@@ -77,6 +77,15 @@ namespace Content.Client.GameObjects.Components.Clothing
var prefix = ClothingEquippedPrefix ?? EquippedPrefix; var prefix = ClothingEquippedPrefix ?? EquippedPrefix;
var stateId = prefix != null ? $"{prefix}-equipped-{slot}" : $"equipped-{slot}"; var stateId = prefix != null ? $"{prefix}-equipped-{slot}" : $"equipped-{slot}";
if (speciesId != null)
{
var speciesState = $"{stateId}-{speciesId}";
if (rsi.TryGetState(speciesState, out _))
{
return (rsi, speciesState);
}
}
if (rsi.TryGetState(stateId, out _)) if (rsi.TryGetState(stateId, out _))
{ {
return (rsi, stateId); return (rsi, stateId);

View File

@@ -2,7 +2,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Client.GameObjects.Components.Clothing; using Content.Client.GameObjects.Components.Clothing;
using Content.Client.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.GameObjects.EntitySystems.EffectBlocker;
@@ -10,6 +9,7 @@ using Content.Shared.Preferences.Appearance;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines; using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
using static Content.Shared.GameObjects.Components.Inventory.SharedInventoryComponent.ClientInventoryMessage; using static Content.Shared.GameObjects.Components.Inventory.SharedInventoryComponent.ClientInventoryMessage;
@@ -34,6 +34,9 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
private bool _playerAttached = false; private bool _playerAttached = false;
[ViewVariables]
[DataField("speciesId")] public string? SpeciesId { get; set; }
public override void OnRemove() public override void OnRemove()
{ {
base.OnRemove(); base.OnRemove();
@@ -182,7 +185,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
if (entity.TryGetComponent(out ClothingComponent? clothing)) if (entity.TryGetComponent(out ClothingComponent? clothing))
{ {
var flag = SlotMasks[slot]; var flag = SlotMasks[slot];
var data = clothing.GetEquippedStateInfo(flag); var data = clothing.GetEquippedStateInfo(flag, SpeciesId);
if (data != null) if (data != null)
{ {
var (rsi, state) = data.Value; var (rsi, state) = data.Value;
@@ -190,7 +193,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
_sprite.LayerSetState(slot, state, rsi); _sprite.LayerSetState(slot, state, rsi);
_sprite.LayerSetAutoAnimated(slot, true); _sprite.LayerSetAutoAnimated(slot, true);
if (slot == Slots.INNERCLOTHING) if (slot == Slots.INNERCLOTHING && _sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
{ {
_sprite.LayerSetState(HumanoidVisualLayers.StencilMask, clothing.FemaleMask switch _sprite.LayerSetState(HumanoidVisualLayers.StencilMask, clothing.FemaleMask switch
{ {

View File

@@ -4,15 +4,15 @@ using Content.Client.UserInterface.Stylesheets;
using Content.Shared.Preferences.Appearance; using Content.Shared.Preferences.Appearance;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using static Content.Shared.GameObjects.Components.SharedMagicMirrorComponent; using static Content.Shared.GameObjects.Components.SharedMagicMirrorComponent;
using static Content.Client.StaticIoC;
namespace Content.Client.GameObjects.Components namespace Content.Client.GameObjects.Components
{ {
@@ -151,47 +151,42 @@ namespace Content.Client.GameObjects.Components
} }
} }
public class FacialHairStylePicker : HairStylePicker public sealed class HairStylePicker : Control
{ {
public override void Populate() [Dependency] private readonly SpriteAccessoryManager _spriteAccessoryManager = default!;
{
var humanFacialHairRSIPath = SharedSpriteComponent.TextureRoot / "Mobs/Customization/human_facial_hair.rsi";
var humanFacialHairRSI = ResC.GetResource<RSIResource>(humanFacialHairRSIPath).RSI;
var styles = HairStyles.FacialHairStylesMap.ToList();
styles.Sort(HairStyles.FacialHairStyleComparer);
foreach (var (styleName, styleState) in HairStyles.FacialHairStylesMap)
{
Items.AddItem(styleName, humanFacialHairRSI[styleState].Frame0);
}
}
}
public class HairStylePicker : Control
{
public event Action<Color>? OnHairColorPicked; public event Action<Color>? OnHairColorPicked;
public event Action<string>? OnHairStylePicked; public event Action<string>? OnHairStylePicked;
protected readonly ItemList Items; private readonly ItemList _items;
private readonly Control _colorContainer;
private readonly ColorSlider _colorSliderR; private readonly ColorSlider _colorSliderR;
private readonly ColorSlider _colorSliderG; private readonly ColorSlider _colorSliderG;
private readonly ColorSlider _colorSliderB; private readonly ColorSlider _colorSliderB;
private Color _lastColor; private Color _lastColor;
private SpriteAccessoryCategories _categories;
public void SetData(Color color, string styleName) public void SetData(Color color, string styleId, SpriteAccessoryCategories categories, bool canColor)
{ {
if (_categories != categories)
{
_categories = categories;
Populate();
}
_colorContainer.Visible = canColor;
_lastColor = color; _lastColor = color;
_colorSliderR.ColorValue = color.RByte; _colorSliderR.ColorValue = color.RByte;
_colorSliderG.ColorValue = color.GByte; _colorSliderG.ColorValue = color.GByte;
_colorSliderB.ColorValue = color.BByte; _colorSliderB.ColorValue = color.BByte;
foreach (var item in Items) foreach (var item in _items)
{ {
item.Selected = item.Text == styleName; var prototype = (SpriteAccessoryPrototype) item.Metadata!;
item.Selected = prototype.ID == styleId;
} }
UpdateStylePickerColor(); UpdateStylePickerColor();
@@ -199,7 +194,7 @@ namespace Content.Client.GameObjects.Components
private void UpdateStylePickerColor() private void UpdateStylePickerColor()
{ {
foreach (var item in Items) foreach (var item in _items)
{ {
item.IconModulate = _lastColor; item.IconModulate = _lastColor;
} }
@@ -207,25 +202,29 @@ namespace Content.Client.GameObjects.Components
public HairStylePicker() public HairStylePicker()
{ {
IoCManager.InjectDependencies(this);
var vBox = new VBoxContainer(); var vBox = new VBoxContainer();
AddChild(vBox); AddChild(vBox);
vBox.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed)); _colorContainer = new VBoxContainer();
vBox.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen)); vBox.AddChild(_colorContainer);
vBox.AddChild(_colorSliderB = new ColorSlider(StyleNano.StyleClassSliderBlue)); _colorContainer.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed));
_colorContainer.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen));
_colorContainer.AddChild(_colorSliderB = new ColorSlider(StyleNano.StyleClassSliderBlue));
Action colorValueChanged = ColorValueChanged; Action colorValueChanged = ColorValueChanged;
_colorSliderR.OnValueChanged += colorValueChanged; _colorSliderR.OnValueChanged += colorValueChanged;
_colorSliderG.OnValueChanged += colorValueChanged; _colorSliderG.OnValueChanged += colorValueChanged;
_colorSliderB.OnValueChanged += colorValueChanged; _colorSliderB.OnValueChanged += colorValueChanged;
Items = new ItemList _items = new ItemList
{ {
VerticalExpand = true, VerticalExpand = true,
MinSize = (300, 250) MinSize = (300, 250)
}; };
vBox.AddChild(Items); vBox.AddChild(_items);
Items.OnItemSelected += ItemSelected; _items.OnItemSelected += ItemSelected;
} }
private void ColorValueChanged() private void ColorValueChanged()
@@ -241,27 +240,28 @@ namespace Content.Client.GameObjects.Components
UpdateStylePickerColor(); UpdateStylePickerColor();
} }
public virtual void Populate() public void Populate()
{ {
var humanHairRSIPath = SharedSpriteComponent.TextureRoot / "Mobs/Customization/human_hair.rsi"; var styles = _spriteAccessoryManager
var humanHairRSI = ResC.GetResource<RSIResource>(humanHairRSIPath).RSI; .AccessoriesForCategory(_categories)
.ToList();
styles.Sort(HairStyles.SpriteAccessoryComparer);
var styles = HairStyles.HairStylesMap.ToList(); foreach (var style in styles)
styles.Sort(HairStyles.HairStyleComparer);
foreach (var (styleName, styleState) in styles)
{ {
Items.AddItem(styleName, humanHairRSI[styleState].Frame0); var item = _items.AddItem(style.Name, style.Sprite.Frame0());
item.Metadata = style;
} }
} }
private void ItemSelected(ItemList.ItemListSelectedEventArgs args) private void ItemSelected(ItemList.ItemListSelectedEventArgs args)
{ {
var hairColor = Items[args.ItemIndex].Text; var prototype = (SpriteAccessoryPrototype?) _items[args.ItemIndex].Metadata;
var style = prototype?.ID;
if (hairColor != null) if (style != null)
{ {
OnHairStylePicked?.Invoke(hairColor); OnHairStylePicked?.Invoke(style);
} }
} }
@@ -321,7 +321,7 @@ namespace Content.Client.GameObjects.Components
public class MagicMirrorWindow : SS14Window public class MagicMirrorWindow : SS14Window
{ {
private readonly HairStylePicker _hairStylePicker; private readonly HairStylePicker _hairStylePicker;
private readonly FacialHairStylePicker _facialHairStylePicker; private readonly HairStylePicker _facialHairStylePicker;
private readonly EyeColorPicker _eyeColorPicker; private readonly EyeColorPicker _eyeColorPicker;
public MagicMirrorWindow(MagicMirrorBoundUserInterface owner) public MagicMirrorWindow(MagicMirrorBoundUserInterface owner)
@@ -330,12 +330,10 @@ namespace Content.Client.GameObjects.Components
Title = Loc.GetString("Magic Mirror"); Title = Loc.GetString("Magic Mirror");
_hairStylePicker = new HairStylePicker {HorizontalExpand = true}; _hairStylePicker = new HairStylePicker {HorizontalExpand = true};
_hairStylePicker.Populate();
_hairStylePicker.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, false); _hairStylePicker.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, false);
_hairStylePicker.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, false); _hairStylePicker.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, false);
_facialHairStylePicker = new FacialHairStylePicker {HorizontalExpand = true}; _facialHairStylePicker = new HairStylePicker {HorizontalExpand = true};
_facialHairStylePicker.Populate();
_facialHairStylePicker.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, true); _facialHairStylePicker.OnHairStylePicked += newStyle => owner.HairSelected(newStyle, true);
_facialHairStylePicker.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, true); _facialHairStylePicker.OnHairColorPicked += newColor => owner.HairColorSelected(newColor, true);
@@ -363,8 +361,8 @@ namespace Content.Client.GameObjects.Components
public void SetInitialData(MagicMirrorInitialDataMessage initialData) public void SetInitialData(MagicMirrorInitialDataMessage initialData)
{ {
_facialHairStylePicker.SetData(initialData.FacialHairColor, initialData.FacialHairName); _facialHairStylePicker.SetData(initialData.FacialHairColor, initialData.FacialHairId, initialData.CategoriesFacialHair, initialData.CanColorFacialHair);
_hairStylePicker.SetData(initialData.HairColor, initialData.HairName); _hairStylePicker.SetData(initialData.HairColor, initialData.HairId, initialData.CategoriesHair, initialData.CanColorHair);
_eyeColorPicker.SetData(initialData.EyeColor); _eyeColorPicker.SetData(initialData.EyeColor);
} }
} }

View File

@@ -6,12 +6,18 @@ using Content.Shared.Preferences;
using Content.Shared.Preferences.Appearance; using Content.Shared.Preferences.Appearance;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.Client.GameObjects.Components.Mobs namespace Content.Client.GameObjects.Components.Mobs
{ {
[RegisterComponent] [RegisterComponent]
public sealed class HumanoidAppearanceComponent : SharedHumanoidAppearanceComponent, IBodyPartAdded, IBodyPartRemoved public sealed class HumanoidAppearanceComponent : SharedHumanoidAppearanceComponent, IBodyPartAdded, IBodyPartRemoved
{ {
[Dependency] private readonly SpriteAccessoryManager _accessoryManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override HumanoidCharacterAppearance Appearance public override HumanoidCharacterAppearance Appearance
{ {
get => base.Appearance; get => base.Appearance;
@@ -60,14 +66,17 @@ namespace Content.Client.GameObjects.Components.Mobs
} }
} }
sprite.LayerSetColor(HumanoidVisualLayers.Hair, Appearance.HairColor); sprite.LayerSetColor(HumanoidVisualLayers.Hair,
sprite.LayerSetColor(HumanoidVisualLayers.FacialHair, Appearance.FacialHairColor); CanColorHair ? Appearance.HairColor : Color.White);
sprite.LayerSetColor(HumanoidVisualLayers.FacialHair,
CanColorFacialHair ? Appearance.FacialHairColor : Color.White);
sprite.LayerSetColor(HumanoidVisualLayers.Eyes, Appearance.EyeColor); sprite.LayerSetColor(HumanoidVisualLayers.Eyes, Appearance.EyeColor);
sprite.LayerSetState(HumanoidVisualLayers.Chest, Sex == Sex.Male ? "torso_m" : "torso_f"); sprite.LayerSetState(HumanoidVisualLayers.Chest, Sex == Sex.Male ? "torso_m" : "torso_f");
sprite.LayerSetState(HumanoidVisualLayers.Head, Sex == Sex.Male ? "head_m" : "head_f"); sprite.LayerSetState(HumanoidVisualLayers.Head, Sex == Sex.Male ? "head_m" : "head_f");
if (sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
sprite.LayerSetVisible(HumanoidVisualLayers.StencilMask, Sex == Sex.Female); sprite.LayerSetVisible(HumanoidVisualLayers.StencilMask, Sex == Sex.Female);
if (Owner.TryGetComponent<CuffableComponent>(out var cuffed)) if (Owner.TryGetComponent<CuffableComponent>(out var cuffed))
@@ -79,17 +88,25 @@ namespace Content.Client.GameObjects.Components.Mobs
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false); sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false);
} }
var hairStyle = Appearance.HairStyleName; var hairStyle = Appearance.HairStyleId;
if (string.IsNullOrWhiteSpace(hairStyle) || !HairStyles.HairStylesMap.ContainsKey(hairStyle)) if (string.IsNullOrWhiteSpace(hairStyle) ||
!_accessoryManager.IsValidAccessoryInCategory(hairStyle, CategoriesHair))
{
hairStyle = HairStyles.DefaultHairStyle; hairStyle = HairStyles.DefaultHairStyle;
sprite.LayerSetState(HumanoidVisualLayers.Hair, }
HairStyles.HairStylesMap[hairStyle]);
var facialHairStyle = Appearance.FacialHairStyleName; var facialHairStyle = Appearance.FacialHairStyleId;
if (string.IsNullOrWhiteSpace(facialHairStyle) || !HairStyles.FacialHairStylesMap.ContainsKey(facialHairStyle)) if (string.IsNullOrWhiteSpace(facialHairStyle) ||
!_accessoryManager.IsValidAccessoryInCategory(facialHairStyle, CategoriesFacialHair))
{
facialHairStyle = HairStyles.DefaultFacialHairStyle; facialHairStyle = HairStyles.DefaultFacialHairStyle;
sprite.LayerSetState(HumanoidVisualLayers.FacialHair, }
HairStyles.FacialHairStylesMap[facialHairStyle]);
var hairPrototype = _prototypeManager.Index<SpriteAccessoryPrototype>(hairStyle);
var facialHairPrototype = _prototypeManager.Index<SpriteAccessoryPrototype>(facialHairStyle);
sprite.LayerSetSprite(HumanoidVisualLayers.Hair, hairPrototype.Sprite);
sprite.LayerSetSprite(HumanoidVisualLayers.FacialHair, facialHairPrototype.Sprite);
} }
public void BodyPartAdded(BodyPartAddedEventArgs args) public void BodyPartAdded(BodyPartAddedEventArgs args)

View File

@@ -125,7 +125,7 @@ namespace Content.Client.UserInterface
}; };
_createNewCharacterButton.OnPressed += args => _createNewCharacterButton.OnPressed += args =>
{ {
preferencesManager.CreateCharacter(HumanoidCharacterProfile.Default()); preferencesManager.CreateCharacter(HumanoidCharacterProfile.Random());
UpdateUI(); UpdateUI();
args.Event.Handle(); args.Event.Handle();
}; };

View File

@@ -7,6 +7,7 @@ using Content.Client.Interfaces;
using Content.Client.UserInterface.Stylesheets; using Content.Client.UserInterface.Stylesheets;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Shared.Preferences.Appearance;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Graphics; using Robust.Client.Graphics;
@@ -46,7 +47,7 @@ namespace Content.Client.UserInterface
private readonly OptionButton _clothingButton; private readonly OptionButton _clothingButton;
private readonly OptionButton _backpackButton; private readonly OptionButton _backpackButton;
private readonly HairStylePicker _hairPicker; private readonly HairStylePicker _hairPicker;
private readonly FacialHairStylePicker _facialHairPicker; private readonly HairStylePicker _facialHairPicker;
private readonly EyeColorPicker _eyesPicker; private readonly EyeColorPicker _eyesPicker;
private readonly List<JobPrioritySelector> _jobPriorities; private readonly List<JobPrioritySelector> _jobPriorities;
@@ -281,7 +282,7 @@ namespace Content.Client.UserInterface
IsDirty = true; IsDirty = true;
}; };
_facialHairPicker = new FacialHairStylePicker(); _facialHairPicker = new HairStylePicker();
_facialHairPicker.Populate(); _facialHairPicker.Populate();
_facialHairPicker.OnHairStylePicked += newStyle => _facialHairPicker.OnHairStylePicked += newStyle =>
@@ -794,10 +795,14 @@ namespace Content.Client.UserInterface
_hairPicker.SetData( _hairPicker.SetData(
Profile.Appearance.HairColor, Profile.Appearance.HairColor,
Profile.Appearance.HairStyleName); Profile.Appearance.HairStyleId,
SpriteAccessoryCategories.HumanHair,
true);
_facialHairPicker.SetData( _facialHairPicker.SetData(
Profile.Appearance.FacialHairColor, Profile.Appearance.FacialHairColor,
Profile.Appearance.FacialHairStyleName); Profile.Appearance.FacialHairStyleId,
SpriteAccessoryCategories.HumanFacialHair,
false);
} }
private void UpdateEyePickers() private void UpdateEyePickers()

View File

@@ -197,9 +197,9 @@ namespace Content.Server.Database
Age = humanoid.Age, Age = humanoid.Age,
Sex = humanoid.Sex.ToString(), Sex = humanoid.Sex.ToString(),
Gender = humanoid.Gender.ToString(), Gender = humanoid.Gender.ToString(),
HairName = appearance.HairStyleName, HairName = appearance.HairStyleId,
HairColor = appearance.HairColor.ToHex(), HairColor = appearance.HairColor.ToHex(),
FacialHairName = appearance.FacialHairStyleName, FacialHairName = appearance.FacialHairStyleId,
FacialHairColor = appearance.FacialHairColor.ToHex(), FacialHairColor = appearance.FacialHairColor.ToHex(),
EyeColor = appearance.EyeColor.ToHex(), EyeColor = appearance.EyeColor.ToHex(),
SkinColor = appearance.SkinColor.ToHex(), SkinColor = appearance.SkinColor.ToHex(),

View File

@@ -7,6 +7,7 @@ using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Preferences.Appearance; using Content.Shared.Preferences.Appearance;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -17,6 +18,8 @@ namespace Content.Server.GameObjects.Components
[ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IActivate))]
public class MagicMirrorComponent : SharedMagicMirrorComponent, IActivate public class MagicMirrorComponent : SharedMagicMirrorComponent, IActivate
{ {
[Dependency] private readonly SpriteAccessoryManager _spriteAccessoryManager = default!;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(MagicMirrorUiKey.Key); [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(MagicMirrorUiKey.Key);
public override void Initialize() public override void Initialize()
@@ -39,7 +42,7 @@ namespace Content.Server.GameObjects.Components
base.OnRemove(); base.OnRemove();
} }
private static void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{ {
if (obj.Session.AttachedEntity == null) if (obj.Session.AttachedEntity == null)
{ {
@@ -54,18 +57,23 @@ namespace Content.Server.GameObjects.Components
switch (obj.Message) switch (obj.Message)
{ {
case HairSelectedMessage msg: case HairSelectedMessage msg:
var map = var cat = msg.IsFacialHair
msg.IsFacialHair ? HairStyles.FacialHairStylesMap : HairStyles.HairStylesMap; ? looks.CategoriesFacialHair
if (!map.ContainsKey(msg.HairName)) : looks.CategoriesHair;
if (!_spriteAccessoryManager.IsValidAccessoryInCategory(msg.HairId, cat))
return; return;
looks.Appearance = msg.IsFacialHair looks.Appearance = msg.IsFacialHair
? looks.Appearance.WithFacialHairStyleName(msg.HairName) ? looks.Appearance.WithFacialHairStyleName(msg.HairId)
: looks.Appearance.WithHairStyleName(msg.HairName); : looks.Appearance.WithHairStyleName(msg.HairId);
break; break;
case HairColorSelectedMessage msg: case HairColorSelectedMessage msg:
if (msg.IsFacialHair ? !looks.CanColorFacialHair : !looks.CanColorHair)
return;
var (r, g, b) = msg.HairColor; var (r, g, b) = msg.HairColor;
var color = new Color(r, g, b); var color = new Color(r, g, b);
@@ -105,9 +113,13 @@ namespace Content.Server.GameObjects.Components
var msg = new MagicMirrorInitialDataMessage( var msg = new MagicMirrorInitialDataMessage(
appearance.HairColor, appearance.HairColor,
appearance.FacialHairColor, appearance.FacialHairColor,
appearance.HairStyleName, appearance.HairStyleId,
appearance.FacialHairStyleName, appearance.FacialHairStyleId,
appearance.EyeColor); appearance.EyeColor,
looks.CategoriesHair,
looks.CategoriesFacialHair,
looks.CanColorHair,
looks.CanColorFacialHair);
UserInterface?.SendMessage(msg, actor.playerSession); UserInterface?.SendMessage(msg, actor.playerSession);
} }

View File

@@ -286,7 +286,7 @@ namespace Content.Server.GameTicking
{ {
if (!profiles.ContainsKey(readyPlayer.UserId)) if (!profiles.ContainsKey(readyPlayer.UserId))
{ {
profiles.Add(readyPlayer.UserId, HumanoidCharacterProfile.Default()); profiles.Add(readyPlayer.UserId, HumanoidCharacterProfile.Random());
} }
} }

View File

@@ -182,7 +182,7 @@ namespace Content.Server.Preferences
{ {
PrefsLoaded = Task.CompletedTask, PrefsLoaded = Task.CompletedTask,
Prefs = new PlayerPreferences( Prefs = new PlayerPreferences(
new[] {new KeyValuePair<int, ICharacterProfile>(0, HumanoidCharacterProfile.Default())}, new[] {new KeyValuePair<int, ICharacterProfile>(0, HumanoidCharacterProfile.Random())},
0, Color.Transparent) 0, Color.Transparent)
}; };
@@ -249,7 +249,7 @@ namespace Content.Server.Preferences
var prefs = await _db.GetPlayerPreferencesAsync(userId); var prefs = await _db.GetPlayerPreferencesAsync(userId);
if (prefs is null) if (prefs is null)
{ {
return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Default()); return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Random());
} }
return SanitizePreferences(prefs); return SanitizePreferences(prefs);

View File

@@ -7,9 +7,10 @@ namespace Content.Shared.Actions
public enum ActionType : byte public enum ActionType : byte
{ {
Error, Error,
HumanScream,
VoxScream,
CombatMode, CombatMode,
Disarm, Disarm,
HumanScream,
GhostBoo, GhostBoo,
DebugInstant, DebugInstant,
DebugToggle, DebugToggle,

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Maps; using Content.Shared.Maps;
using Content.Shared.Preferences.Appearance;
using Robust.Shared.ContentPack; using Robust.Shared.ContentPack;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Log;
@@ -19,6 +20,7 @@ namespace Content.Shared
public override void PreInit() public override void PreInit()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
SharedContentIoC.Register();
Localization.Init(); Localization.Init();
} }
@@ -33,6 +35,7 @@ namespace Content.Shared
_initTileDefinitions(); _initTileDefinitions();
CheckReactions(); CheckReactions();
IoCManager.Resolve<SpriteAccessoryManager>().Initialize();
} }
private void CheckReactions() private void CheckReactions()

View File

@@ -1,23 +1,41 @@
#nullable enable #nullable enable
using System; using System;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Shared.Preferences.Appearance;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Players; using Robust.Shared.Players;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs namespace Content.Shared.GameObjects.Components.Mobs
{ {
public abstract class SharedHumanoidAppearanceComponent : Component public abstract class SharedHumanoidAppearanceComponent : Component
{ {
private HumanoidCharacterAppearance _appearance = default!; private HumanoidCharacterAppearance _appearance = HumanoidCharacterAppearance.Default();
private Sex _sex; private Sex _sex;
private Gender _gender; private Gender _gender;
public sealed override string Name => "HumanoidAppearance"; public sealed override string Name => "HumanoidAppearance";
public sealed override uint? NetID => ContentNetIDs.HUMANOID_APPEARANCE; public sealed override uint? NetID => ContentNetIDs.HUMANOID_APPEARANCE;
[DataField("categoriesHair")]
[ViewVariables]
public SpriteAccessoryCategories CategoriesHair { get; set; } = SpriteAccessoryCategories.HumanHair;
[DataField("categoriesFacialHair")]
[ViewVariables]
public SpriteAccessoryCategories CategoriesFacialHair { get; set; } = SpriteAccessoryCategories.HumanFacialHair;
[ViewVariables]
[DataField("canColorHair")]
public bool CanColorHair { get; set; } = true;
[ViewVariables]
[DataField("canColorFacialHair")]
public bool CanColorFacialHair { get; set; } = true;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public virtual HumanoidCharacterAppearance Appearance public virtual HumanoidCharacterAppearance Appearance
{ {
@@ -80,7 +98,8 @@ namespace Content.Shared.GameObjects.Components.Mobs
[NetSerializable] [NetSerializable]
private sealed class HumanoidAppearanceComponentState : ComponentState private sealed class HumanoidAppearanceComponentState : ComponentState
{ {
public HumanoidAppearanceComponentState(HumanoidCharacterAppearance appearance, Sex sex, Gender gender) : base(ContentNetIDs.HUMANOID_APPEARANCE) public HumanoidAppearanceComponentState(HumanoidCharacterAppearance appearance, Sex sex, Gender gender) :
base(ContentNetIDs.HUMANOID_APPEARANCE)
{ {
Appearance = appearance; Appearance = appearance;
Sex = sex; Sex = sex;

View File

@@ -1,5 +1,6 @@
#nullable enable #nullable enable
using System; using System;
using Content.Shared.Preferences.Appearance;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
@@ -19,12 +20,12 @@ namespace Content.Shared.GameObjects.Components
[Serializable, NetSerializable] [Serializable, NetSerializable]
public class HairSelectedMessage : BoundUserInterfaceMessage public class HairSelectedMessage : BoundUserInterfaceMessage
{ {
public readonly string HairName; public readonly string HairId;
public readonly bool IsFacialHair; public readonly bool IsFacialHair;
public HairSelectedMessage(string name, bool isFacialHair) public HairSelectedMessage(string id, bool isFacialHair)
{ {
HairName = name; HairId = id;
IsFacialHair = isFacialHair; IsFacialHair = isFacialHair;
} }
} }
@@ -58,17 +59,25 @@ namespace Content.Shared.GameObjects.Components
{ {
public readonly Color HairColor; public readonly Color HairColor;
public readonly Color FacialHairColor; public readonly Color FacialHairColor;
public readonly string HairName; public readonly string HairId;
public readonly string FacialHairName; public readonly string FacialHairId;
public readonly Color EyeColor; public readonly Color EyeColor;
public readonly SpriteAccessoryCategories CategoriesHair;
public readonly SpriteAccessoryCategories CategoriesFacialHair;
public readonly bool CanColorHair;
public readonly bool CanColorFacialHair;
public MagicMirrorInitialDataMessage(Color hairColor, Color facialHairColor, string hairName, string facialHairName, Color eyeColor) public MagicMirrorInitialDataMessage(Color hairColor, Color facialHairColor, string hairId, string facialHairId, Color eyeColor, SpriteAccessoryCategories categoriesHair, SpriteAccessoryCategories categoriesFacialHair, bool canColorHair, bool canColorFacialHair)
{ {
HairColor = hairColor; HairColor = hairColor;
FacialHairColor = facialHairColor; FacialHairColor = facialHairColor;
HairName = hairName; HairId = hairId;
FacialHairName = facialHairName; FacialHairId = facialHairId;
EyeColor = eyeColor; EyeColor = eyeColor;
CategoriesHair = categoriesHair;
CategoriesFacialHair = categoriesFacialHair;
CanColorHair = canColorHair;
CanColorFacialHair = canColorFacialHair;
} }
} }
} }

View File

@@ -1,277 +1,16 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Robust.Shared.Maths; using Robust.Shared.Maths;
namespace Content.Shared.Preferences.Appearance namespace Content.Shared.Preferences.Appearance
{ {
[SuppressMessage("ReSharper", "StringLiteralTypo")]
public static class HairStyles public static class HairStyles
{ {
public const string DefaultHairStyle = "Bald"; public const string DefaultHairStyle = "HairBald";
public const string DefaultFacialHairStyle = "Shaved"; public const string DefaultFacialHairStyle = "FacialHairShaved";
public static readonly Dictionary<string, string> HairStylesMap = new() public static readonly IReadOnlyList<Color> RealisticHairColors = new List<Color>
{
{"Afro", "afro"},
{"Afro 2", "afro2"},
{"Afro (Large)", "bigafro"},
{"Ahoge", "antenna"},
{"Bald", "bald"},
{"Balding Hair", "e"},
{"Bedhead", "bedhead"},
{"Bedhead 2", "bedheadv2"},
{"Bedhead 3", "bedheadv3"},
{"Long Bedhead", "long_bedhead"},
{"Floorlength Bedhead", "floorlength_bedhead"},
{"Beehive", "beehive"},
{"Beehive 2", "beehivev2"},
{"Bob Hair", "bob"},
{"Bob Hair 2", "bob2"},
{"Bob Hair 3", "bobcut"},
{"Bob Hair 4", "bob4"},
{"Bobcurl", "bobcurl"},
{"Boddicker", "boddicker"},
{"Bowlcut", "bowlcut"},
{"Bowlcut 2", "bowlcut2"},
{"Braid (Floorlength)", "braid"},
{"Braided", "braided"},
{"Braided Front", "braidfront"},
{"Braid (High)", "braid2"},
{"Braid (Low)", "hbraid"},
{"Braid (Short)", "shortbraid"},
{"Braided Tail", "braidtail"},
{"Bun Head", "bun"},
{"Bun Head 2", "bunhead2"},
{"Bun Head 3", "bun3"},
{"Bun (Large)", "largebun"},
{"Bun (Manbun)", "manbun"},
{"Bun (Tight)", "tightbun"},
{"Business Hair", "business"},
{"Business Hair 2", "business2"},
{"Business Hair 3", "business3"},
{"Business Hair 4", "business4"},
{"Buzzcut", "buzzcut"},
{"CIA", "cia"},
{"Coffee House", "coffeehouse"},
{"Combover", "combover"},
{"Cornrows", "cornrows"},
{"Cornrows 2", "cornrows2"},
{"Cornrow Bun", "cornrowbun"},
{"Cornrow Braid", "cornrowbraid"},
{"Cornrow Tail", "cornrowtail"},
{"Crewcut", "crewcut"},
{"Curls", "curls"},
{"Cut Hair", "c"},
{"Dandy Pompadour", "dandypompadour"},
{"Devil Lock", "devilock"},
{"Double Bun", "doublebun"},
{"Dreadlocks", "dreads"},
{"Drillruru", "drillruru"},
{"Drill Hair (Extended)", "drillhairextended"},
{"Emo", "emo"},
{"Emo Fringe", "emofringe"},
{"Fade (None)", "nofade"},
{"Fade (High)", "highfade"},
{"Fade (Medium)", "medfade"},
{"Fade (Low)", "lowfade"},
{"Fade (Bald)", "baldfade"},
{"Feather", "feather"},
{"Father", "father"},
{"Flat Top", "sargeant"},
{"Flair", "flair"},
{"Flat Top (Big)", "bigflattop"},
{"Flow Hair", "f"},
{"Gelled Back", "gelled"},
{"Gentle", "gentle"},
{"Half-banged Hair", "halfbang"},
{"Half-banged Hair 2", "halfbang2"},
{"Half-shaved", "halfshaved"},
{"Hedgehog Hair", "hedgehog"},
{"Hime Cut", "himecut"},
{"Hime Cut 2", "himecut2"},
{"Hime Cut (Short)", "shorthime"},
{"Hime Updo", "himeup"},
{"Hitop", "hitop"},
{"Jade", "jade"},
{"Jensen Hair", "jensen"},
{"Joestar", "joestar"},
{"Keanu Hair", "keanu"},
{"Kusanagi Hair", "kusanagi"},
{"Long Hair 1", "long"},
{"Long Hair 2", "long2"},
{"Long Hair 3", "long3"},
{"Long Over Eye", "longovereye"},
{"Long Bangs", "lbangs"},
{"Long Emo", "longemo"},
{"Long Fringe", "longfringe"},
{"Long Side Part", "longsidepart"},
{"Mega Eyebrows", "megaeyebrows"},
{"Messy", "messy"},
{"Modern", "modern"},
{"Mohawk", "d"},
{"Nitori", "nitori"},
{"Mohawk (Reverse)", "reversemohawk"},
{"Mohawk (Unshaven)", "unshaven_mohawk"},
{"Mulder", "mulder"},
{"Odango", "odango"},
{"Ombre", "ombre"},
{"One Shoulder", "oneshoulder"},
{"Over Eye", "shortovereye"},
{"Oxton", "oxton"},
{"Parted", "parted"},
{"Parted (Side)", "part"},
{"Pigtails", "kagami"},
{"Pigtails 2", "pigtails"},
{"Pigtails 3", "pigtails2"},
{"Pixie Cut", "pixie"},
{"Pompadour", "pompadour"},
{"Pompadour (Big)", "bigpompadour"},
{"Ponytail", "ponytail"},
{"Ponytail 2", "ponytail2"},
{"Ponytail 3", "ponytail3"},
{"Ponytail 4", "ponytail4"},
{"Ponytail 5", "ponytail5"},
{"Ponytail 6", "ponytail6"},
{"Ponytail 7", "ponytail7"},
{"Ponytail (High)", "highponytail"},
{"Ponytail (Short)", "stail"},
{"Ponytail (Long)", "longstraightponytail"},
{"Ponytail (Country)", "country"},
{"Ponytail (Fringe)", "fringetail"},
{"Ponytail (Side)", "sidetail"},
{"Ponytail (Side) 2", "sidetail2"},
{"Ponytail (Side) 3", "sidetail3"},
{"Ponytail (Side) 4", "sidetail4"},
{"Ponytail (Spiky)", "spikyponytail"},
{"Poofy", "poofy"},
{"Quiff", "quiff"},
{"Ronin", "ronin"},
{"Shaved", "shaved"},
{"Shaved Part", "shavedpart"},
{"Short Bangs", "shortbangs"},
{"Short Hair", "a"},
{"Short Hair 2", "shorthair2"},
{"Short Hair 3", "shorthair3"},
{"Short Hair 4", "d"},
{"Short Hair 5", "e"},
{"Short Hair 6", "f"},
{"Short Hair 7", "shorthairg"},
{"Short Hair 80s", "80s"},
{"Short Hair Rosa", "rosa"},
{"Shoulder-length Hair", "b"},
{"Sidecut", "sidecut"},
{"Skinhead", "skinhead"},
{"Slightly Long Hair", "protagonist"},
{"Spiky", "spikey"},
{"Spiky 2", "spiky"},
{"Spiky 3", "spiky2"},
{"Swept Back Hair", "swept"},
{"Swept Back Hair 2", "swept2"},
{"Thinning", "thinning"},
{"Thinning (Front)", "thinningfront"},
{"Thinning (Rear)", "thinningrear"},
{"Topknot", "topknot"},
{"Tress Shoulder", "tressshoulder"},
{"Trimmed", "trimmed"},
{"Trim Flat", "trimflat"},
{"Twintails", "twintail"},
{"Undercut", "undercut"},
{"Undercut Left", "undercutleft"},
{"Undercut Right", "undercutright"},
{"Unkept", "unkept"},
{"Updo", "updo"},
{"Very Long Hair", "vlong"},
{"Very Long Hair 2", "longest"},
{"Very Long Over Eye", "longest2"},
{"Very Short Over Eye", "veryshortovereyealternate"},
{"Very Long with Fringe", "vlongfringe"},
{"Volaju", "volaju"},
{"Wisp", "wisp"},
};
public static readonly Dictionary<string, string> FacialHairStylesMap = new()
{
{"Beard (Abraham Lincoln)", "abe"},
{"Beard (Broken Man)", "brokenman"},
{"Beard (Chinstrap)", "chin"},
{"Beard (Dwarf)", "dwarf"},
{"Beard (Full)", "fullbeard"},
{"Beard (Cropped Fullbeard)", "croppedfullbeard"},
{"Beard (Goatee)", "gt"},
{"Beard (Hipster)", "hip"},
{"Beard (Jensen)", "jensen"},
{"Beard (Neckbeard)", "neckbeard"},
{"Beard (Very Long)", "wise"},
{"Beard (Muttonmus)", "muttonmus"},
{"Beard (Martial Artist)", "martialartist"},
{"Beard (Chinless Beard)", "chinlessbeard"},
{"Beard (Moonshiner)", "moonshiner"},
{"Beard (Long)", "longbeard"},
{"Beard (Volaju)", "volaju"},
{"Beard (Three o Clock Shadow)", "3oclock"},
{"Beard (Five o Clock Shadow)", "fiveoclock"},
{"Beard (Five o Clock Moustache)", "5oclockmoustache"},
{"Beard (Seven o Clock Shadow)", "7oclock"},
{"Beard (Seven o Clock Moustache)", "7oclockmoustache"},
{"Moustache", "moustache"},
{"Moustache (Pencilstache)", "pencilstache"},
{"Moustache (Smallstache)", "smallstache"},
{"Moustache (Walrus)", "walrus"},
{"Moustache (Fu Manchu)", "fumanchu"},
{"Moustache (Hulk Hogan)", "hogan"},
{"Moustache (Selleck)", "selleck"},
{"Moustache (Square)", "chaplin"},
{"Moustache (Van Dyke)", "vandyke"},
{"Moustache (Watson)", "watson"},
{"Sideburns (Elvis)", "elvis"},
{"Sideburns (Mutton Chops)", "mutton"},
{"Sideburns", "sideburn"},
{"Shaved", "shaved"}
};
// These comparers put the default hair style (shaved/bald) at the very top.
// For in the hair style pickers.
public static readonly IComparer<KeyValuePair<string, string>> HairStyleComparer =
Comparer<KeyValuePair<string, string>>.Create((a, b) =>
{
var styleA = a.Key;
var styleB = b.Key;
if (styleA == DefaultHairStyle)
{
return -1;
}
if (styleB == DefaultHairStyle)
{
return 1;
}
return string.Compare(styleA, styleB, StringComparison.CurrentCulture);
});
public static readonly IComparer<KeyValuePair<string, string>> FacialHairStyleComparer =
Comparer<KeyValuePair<string, string>>.Create((a, b) =>
{
var styleA = a.Key;
var styleB = b.Key;
if (styleA == DefaultFacialHairStyle)
{
return -1;
}
if (styleB == DefaultFacialHairStyle)
{
return 1;
}
return string.Compare(styleA, styleB, StringComparison.CurrentCulture);
});
public static IReadOnlyList<Color> RealisticHairColors = new List<Color>
{ {
Color.Yellow, Color.Yellow,
Color.Black, Color.Black,
@@ -280,5 +19,18 @@ namespace Content.Shared.Preferences.Appearance
Color.Wheat, Color.Wheat,
Color.Gray Color.Gray
}; };
// These comparers put the default hair style (shaved/bald) at the very top.
// For in the hair style pickers.
public static readonly IComparer<SpriteAccessoryPrototype> SpriteAccessoryComparer =
Comparer<SpriteAccessoryPrototype>.Create((a, b) =>
{
var cmp = -a.Priority.CompareTo(b.Priority);
if (cmp != 0)
return cmp;
return string.Compare(a.ID, b.ID, StringComparison.CurrentCulture);
});
} }
} }

View File

@@ -0,0 +1,16 @@
using System;
using Robust.Shared.Serialization;
namespace Content.Shared.Preferences.Appearance
{
[Flags]
[Serializable, NetSerializable]
public enum SpriteAccessoryCategories
{
None = 0,
HumanHair = 1 << 0,
HumanFacialHair = 1 << 1,
VoxHair = 1 << 2,
VoxFacialHair = 1 << 3
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
namespace Content.Shared.Preferences.Appearance
{
public sealed class SpriteAccessoryManager
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly Dictionary<SpriteAccessoryCategories, List<SpriteAccessoryPrototype>> _index = new();
public void Initialize()
{
_prototypeManager.PrototypesReloaded += OnPrototypesReloaded;
foreach (var category in Enum.GetValues<SpriteAccessoryCategories>())
{
_index.Add(category, new List<SpriteAccessoryPrototype>());
}
foreach (var prototype in _prototypeManager.EnumeratePrototypes<SpriteAccessoryPrototype>())
{
AddToIndexes(prototype);
}
}
public IReadOnlyList<SpriteAccessoryPrototype> AccessoriesForCategory(SpriteAccessoryCategories categories)
{
return _index[categories];
}
public bool IsValidAccessoryInCategory(string accessory, SpriteAccessoryCategories categories)
{
return _prototypeManager.TryIndex(accessory, out SpriteAccessoryPrototype? accessoryPrototype)
&& (accessoryPrototype.Categories & categories) != 0;
}
private void OnPrototypesReloaded(PrototypesReloadedEventArgs eventArgs)
{
if (!eventArgs.ByType.TryGetValue(typeof(SpriteAccessoryPrototype), out var set))
return;
foreach (var list in _index.Values)
{
list.RemoveAll(a => set.Modified.ContainsKey(a.ID));
}
foreach (var prototype in set.Modified.Values)
{
var accessoryPrototype = (SpriteAccessoryPrototype) prototype;
AddToIndexes(accessoryPrototype);
}
}
private void AddToIndexes(SpriteAccessoryPrototype accessoryPrototype)
{
for (var i = 0; i < sizeof(SpriteAccessoryCategories) * 8; i++)
{
var flag = (SpriteAccessoryCategories) (1 << i);
if ((accessoryPrototype.Categories & flag) != 0)
_index[flag].Add(accessoryPrototype);
}
}
}
}

View File

@@ -0,0 +1,33 @@
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Shared.Preferences.Appearance
{
/// <summary>
/// Contains data for a single hair style
/// </summary>
[Prototype("spriteAccessory")]
public sealed class SpriteAccessoryPrototype : IPrototype, ISerializationHooks
{
[field: DataField("id", required: true)]
public string ID { get; } = default!;
[field: DataField("categories", required: true)]
public SpriteAccessoryCategories Categories { get; } = default!;
public string Name { get; private set; } = default!;
[field: DataField("sprite", required: true)]
public SpriteSpecifier Sprite { get; } = default!;
[field: DataField("priority")] public int Priority { get; } = 0;
void ISerializationHooks.AfterDeserialization()
{
Name = Loc.GetString($"accessory-{ID}");
}
}
}

View File

@@ -1,6 +1,5 @@
#nullable enable #nullable enable
using System; using System;
using System.Linq;
using Content.Shared.Preferences.Appearance; using Content.Shared.Preferences.Appearance;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
@@ -12,64 +11,64 @@ namespace Content.Shared.Preferences
[Serializable, NetSerializable] [Serializable, NetSerializable]
public class HumanoidCharacterAppearance : ICharacterAppearance public class HumanoidCharacterAppearance : ICharacterAppearance
{ {
public HumanoidCharacterAppearance(string hairStyleName, public HumanoidCharacterAppearance(string hairStyleId,
Color hairColor, Color hairColor,
string facialHairStyleName, string facialHairStyleId,
Color facialHairColor, Color facialHairColor,
Color eyeColor, Color eyeColor,
Color skinColor) Color skinColor)
{ {
HairStyleName = hairStyleName; HairStyleId = hairStyleId;
HairColor = ClampColor(hairColor); HairColor = ClampColor(hairColor);
FacialHairStyleName = facialHairStyleName; FacialHairStyleId = facialHairStyleId;
FacialHairColor = ClampColor(facialHairColor); FacialHairColor = ClampColor(facialHairColor);
EyeColor = ClampColor(eyeColor); EyeColor = ClampColor(eyeColor);
SkinColor = ClampColor(skinColor); SkinColor = ClampColor(skinColor);
} }
public string HairStyleName { get; } public string HairStyleId { get; }
public Color HairColor { get; } public Color HairColor { get; }
public string FacialHairStyleName { get; } public string FacialHairStyleId { get; }
public Color FacialHairColor { get; } public Color FacialHairColor { get; }
public Color EyeColor { get; } public Color EyeColor { get; }
public Color SkinColor { get; } public Color SkinColor { get; }
public HumanoidCharacterAppearance WithHairStyleName(string newName) public HumanoidCharacterAppearance WithHairStyleName(string newName)
{ {
return new(newName, HairColor, FacialHairStyleName, FacialHairColor, EyeColor, SkinColor); return new(newName, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor);
} }
public HumanoidCharacterAppearance WithHairColor(Color newColor) public HumanoidCharacterAppearance WithHairColor(Color newColor)
{ {
return new(HairStyleName, newColor, FacialHairStyleName, FacialHairColor, EyeColor, SkinColor); return new(HairStyleId, newColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor);
} }
public HumanoidCharacterAppearance WithFacialHairStyleName(string newName) public HumanoidCharacterAppearance WithFacialHairStyleName(string newName)
{ {
return new(HairStyleName, HairColor, newName, FacialHairColor, EyeColor, SkinColor); return new(HairStyleId, HairColor, newName, FacialHairColor, EyeColor, SkinColor);
} }
public HumanoidCharacterAppearance WithFacialHairColor(Color newColor) public HumanoidCharacterAppearance WithFacialHairColor(Color newColor)
{ {
return new(HairStyleName, HairColor, FacialHairStyleName, newColor, EyeColor, SkinColor); return new(HairStyleId, HairColor, FacialHairStyleId, newColor, EyeColor, SkinColor);
} }
public HumanoidCharacterAppearance WithEyeColor(Color newColor) public HumanoidCharacterAppearance WithEyeColor(Color newColor)
{ {
return new(HairStyleName, HairColor, FacialHairStyleName, FacialHairColor, newColor, SkinColor); return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, newColor, SkinColor);
} }
public HumanoidCharacterAppearance WithSkinColor(Color newColor) public HumanoidCharacterAppearance WithSkinColor(Color newColor)
{ {
return new(HairStyleName, HairColor, FacialHairStyleName, FacialHairColor, EyeColor, newColor); return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, newColor);
} }
public static HumanoidCharacterAppearance Default() public static HumanoidCharacterAppearance Default()
{ {
return new( return new(
"Bald", HairStyles.DefaultHairStyle,
Color.Black, Color.Black,
"Shaved", HairStyles.DefaultFacialHairStyle,
Color.Black, Color.Black,
Color.Black, Color.Black,
Color.FromHex("#C0967F") Color.FromHex("#C0967F")
@@ -79,12 +78,15 @@ namespace Content.Shared.Preferences
public static HumanoidCharacterAppearance Random(Sex sex) public static HumanoidCharacterAppearance Random(Sex sex)
{ {
var random = IoCManager.Resolve<IRobustRandom>(); var random = IoCManager.Resolve<IRobustRandom>();
var prototypes = IoCManager.Resolve<SpriteAccessoryManager>();
var hairStyles = prototypes.AccessoriesForCategory(SpriteAccessoryCategories.HumanHair);
var facialHairStyles = prototypes.AccessoriesForCategory(SpriteAccessoryCategories.HumanHair);
var newHairStyle = random.Pick(HairStyles.HairStylesMap.Keys.ToList()); var newHairStyle = random.Pick(hairStyles).ID;
var newFacialHairStyle = sex == Sex.Female var newFacialHairStyle = sex == Sex.Female
? HairStyles.DefaultFacialHairStyle ? HairStyles.DefaultFacialHairStyle
: random.Pick(HairStyles.FacialHairStylesMap.Keys.ToList()); : random.Pick(facialHairStyles).ID;
var newHairColor = random.Pick(HairStyles.RealisticHairColors); var newHairColor = random.Pick(HairStyles.RealisticHairColors);
newHairColor = newHairColor newHairColor = newHairColor
@@ -108,24 +110,17 @@ namespace Content.Shared.Preferences
public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance) public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance)
{ {
string hairStyleName; var mgr = IoCManager.Resolve<SpriteAccessoryManager>();
if (!HairStyles.HairStylesMap.ContainsKey(appearance.HairStyleName)) var hairStyleId = appearance.HairStyleId;
if (!mgr.IsValidAccessoryInCategory(hairStyleId, SpriteAccessoryCategories.HumanHair))
{ {
hairStyleName = HairStyles.DefaultHairStyle; hairStyleId = HairStyles.DefaultHairStyle;
}
else
{
hairStyleName = appearance.HairStyleName;
} }
string facialHairStyleName; var facialHairStyleId = appearance.HairStyleId;
if (!HairStyles.FacialHairStylesMap.ContainsKey(appearance.FacialHairStyleName)) if (!mgr.IsValidAccessoryInCategory(hairStyleId, SpriteAccessoryCategories.HumanFacialHair))
{ {
facialHairStyleName = HairStyles.DefaultFacialHairStyle; facialHairStyleId = HairStyles.DefaultFacialHairStyle;
}
else
{
facialHairStyleName = appearance.FacialHairStyleName;
} }
var hairColor = ClampColor(appearance.HairColor); var hairColor = ClampColor(appearance.HairColor);
@@ -134,9 +129,9 @@ namespace Content.Shared.Preferences
var skinColor = ClampColor(appearance.SkinColor); var skinColor = ClampColor(appearance.SkinColor);
return new HumanoidCharacterAppearance( return new HumanoidCharacterAppearance(
hairStyleName, hairStyleId,
hairColor, hairColor,
facialHairStyleName, facialHairStyleId,
facialHairColor, facialHairColor,
eyeColor, eyeColor,
skinColor); skinColor);
@@ -145,9 +140,9 @@ namespace Content.Shared.Preferences
public bool MemberwiseEquals(ICharacterAppearance maybeOther) public bool MemberwiseEquals(ICharacterAppearance maybeOther)
{ {
if (maybeOther is not HumanoidCharacterAppearance other) return false; if (maybeOther is not HumanoidCharacterAppearance other) return false;
if (HairStyleName != other.HairStyleName) return false; if (HairStyleId != other.HairStyleId) return false;
if (!HairColor.Equals(other.HairColor)) return false; if (!HairColor.Equals(other.HairColor)) return false;
if (FacialHairStyleName != other.FacialHairStyleName) return false; if (FacialHairStyleId != other.FacialHairStyleId) return false;
if (!FacialHairColor.Equals(other.FacialHairColor)) return false; if (!FacialHairColor.Equals(other.FacialHairColor)) return false;
if (!EyeColor.Equals(other.EyeColor)) return false; if (!EyeColor.Equals(other.EyeColor)) return false;
if (!SkinColor.Equals(other.SkinColor)) return false; if (!SkinColor.Equals(other.SkinColor)) return false;

View File

@@ -21,11 +21,12 @@ namespace Content.Shared.Preferences
[Serializable, NetSerializable] [Serializable, NetSerializable]
public class HumanoidCharacterProfile : ICharacterProfile public class HumanoidCharacterProfile : ICharacterProfile
{ {
public const int MinimumAge = 18;
public const int MaximumAge = 120;
public const int MaxNameLength = 32;
private readonly Dictionary<string, JobPriority> _jobPriorities; private readonly Dictionary<string, JobPriority> _jobPriorities;
private readonly List<string> _antagPreferences; private readonly List<string> _antagPreferences;
public static int MinimumAge = 18;
public static int MaximumAge = 120;
public static int MaxNameLength = 32;
private HumanoidCharacterProfile( private HumanoidCharacterProfile(
string name, string name,
@@ -85,7 +86,20 @@ namespace Content.Shared.Preferences
public static HumanoidCharacterProfile Default() public static HumanoidCharacterProfile Default()
{ {
return Random(); return new(
"John Doe",
MinimumAge,
Sex.Male,
Gender.Male,
HumanoidCharacterAppearance.Default(),
ClothingPreference.Jumpsuit,
BackpackPreference.Backpack,
new Dictionary<string, JobPriority>
{
{SharedGameTicker.OverflowJob, JobPriority.High}
},
PreferenceUnavailableMode.SpawnAsOverflow,
new List<string>());
} }
public static HumanoidCharacterProfile Random() public static HumanoidCharacterProfile Random()

View File

@@ -0,0 +1,13 @@
using Content.Shared.Preferences.Appearance;
using Robust.Shared.IoC;
namespace Content.Shared
{
public static class SharedContentIoC
{
public static void Register()
{
IoCManager.Register<SpriteAccessoryManager, SpriteAccessoryManager>();
}
}
}

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Content.Client; using Content.Client;
using Content.Server; using Content.Server;
using Content.Shared;
using Robust.UnitTesting; using Robust.UnitTesting;
namespace Content.Tests namespace Content.Tests
@@ -12,6 +13,8 @@ namespace Content.Tests
{ {
base.OverrideIoC(); base.OverrideIoC();
SharedContentIoC.Register();
if (Project == UnitTestProject.Server) if (Project == UnitTestProject.Server)
{ {
ServerContentIoC.Register(); ServerContentIoC.Register();

Binary file not shown.

View File

@@ -0,0 +1,2 @@
accessory-HairBald = Bald
accessory-FacialHairShaved = Shaved

View File

@@ -0,0 +1,35 @@
accessory-HumanFacialHairAbe = Beard (Abraham Lincoln)
accessory-HumanFacialHairBrokenman = Beard (Broken Man)
accessory-HumanFacialHairChin = Beard (Chinstrap)
accessory-HumanFacialHairDwarf = Beard (Dwarf)
accessory-HumanFacialHairFullbeard = Beard (Full)
accessory-HumanFacialHairCroppedfullbeard = Beard (Cropped Fullbeard)
accessory-HumanFacialHairGt = Beard (Goatee)
accessory-HumanFacialHairHip = Beard (Hipster)
accessory-HumanFacialHairJensen = Beard (Jensen)
accessory-HumanFacialHairNeckbeard = Beard (Neckbeard)
accessory-HumanFacialHairWise = Beard (Very Long)
accessory-HumanFacialHairMuttonmus = Beard (Muttonmus)
accessory-HumanFacialHairMartialartist = Beard (Martial Artist)
accessory-HumanFacialHairChinlessbeard = Beard (Chinless Beard)
accessory-HumanFacialHairMoonshiner = Beard (Moonshiner)
accessory-HumanFacialHairLongbeard = Beard (Long)
accessory-HumanFacialHairVolaju = Beard (Volaju)
accessory-HumanFacialHair3oclock = Beard (Three o Clock Shadow)
accessory-HumanFacialHairFiveoclock = Beard (Five o Clock Shadow)
accessory-HumanFacialHair5oclockmoustache = Beard (Five o Clock Moustache)
accessory-HumanFacialHair7oclock = Beard (Seven o Clock Shadow)
accessory-HumanFacialHair7oclockmoustache = Beard (Seven o Clock Moustache)
accessory-HumanFacialHairMoustache = Moustache
accessory-HumanFacialHairPencilstache = Moustache (Pencilstache)
accessory-HumanFacialHairSmallstache = Moustache (Smallstache)
accessory-HumanFacialHairWalrus = Moustache (Walrus)
accessory-HumanFacialHairFumanchu = Moustache (Fu Manchu)
accessory-HumanFacialHairHogan = Moustache (Hulk Hogan)
accessory-HumanFacialHairSelleck = Moustache (Selleck)
accessory-HumanFacialHairChaplin = Moustache (Square)
accessory-HumanFacialHairVandyke = Moustache (Van Dyke)
accessory-HumanFacialHairWatson = Moustache (Watson)
accessory-HumanFacialHairElvis = Sideburns (Elvis)
accessory-HumanFacialHairMutton = Sideburns (Mutton Chops)
accessory-HumanFacialHairSideburn = Sideburns

View File

@@ -0,0 +1,174 @@
accessory-HumanHairAfro = Afro
accessory-HumanHairAfro2 = Afro 2
accessory-HumanHairBigafro = Afro (Large)
accessory-HumanHairAntenna = Ahoge
accessory-HumanHairBalding = Balding Hair
accessory-HumanHairBedhead = Bedhead
accessory-HumanHairBedheadv2 = Bedhead 2
accessory-HumanHairBedheadv3 = Bedhead 3
accessory-HumanHairLongBedhead = Long Bedhead
accessory-HumanHairFloorlengthBedhead = Floorlength Bedhead
accessory-HumanHairBeehive = Beehive
accessory-HumanHairBeehivev2 = Beehive 2
accessory-HumanHairBob = Bob Hair
accessory-HumanHairBob2 = Bob Hair 2
accessory-HumanHairBobcut = Bob Hair 3
accessory-HumanHairBob4 = Bob Hair 4
accessory-HumanHairBobcurl = Bobcurl
accessory-HumanHairBoddicker = Boddicker
accessory-HumanHairBowlcut = Bowlcut
accessory-HumanHairBowlcut2 = Bowlcut 2
accessory-HumanHairBraid = Braid (Floorlength)
accessory-HumanHairBraided = Braided
accessory-HumanHairBraidfront = Braided Front
accessory-HumanHairBraid2 = Braid (High)
accessory-HumanHairHbraid = Braid (Low)
accessory-HumanHairShortbraid = Braid (Short)
accessory-HumanHairBraidtail = Braided Tail
accessory-HumanHairBun = Bun Head
accessory-HumanHairBunhead2 = Bun Head 2
accessory-HumanHairBun3 = Bun Head 3
accessory-HumanHairLargebun = Bun (Large)
accessory-HumanHairManbun = Bun (Manbun)
accessory-HumanHairTightbun = Bun (Tight)
accessory-HumanHairBusiness = Business Hair
accessory-HumanHairBusiness2 = Business Hair 2
accessory-HumanHairBusiness3 = Business Hair 3
accessory-HumanHairBusiness4 = Business Hair 4
accessory-HumanHairBuzzcut = Buzzcut
accessory-HumanHairCia = CIA
accessory-HumanHairCoffeehouse = Coffee House
accessory-HumanHairCombover = Combover
accessory-HumanHairCornrows = Cornrows
accessory-HumanHairCornrows2 = Cornrows 2
accessory-HumanHairCornrowbun = Cornrow Bun
accessory-HumanHairCornrowbraid = Cornrow Braid
accessory-HumanHairCornrowtail = Cornrow Tail
accessory-HumanHairCrewcut = Crewcut
accessory-HumanHairCurls = Curls
accessory-HumanHairC = Cut Hair
accessory-HumanHairDandypompadour = Dandy Pompadour
accessory-HumanHairDevilock = Devil Lock
accessory-HumanHairDoublebun = Double Bun
accessory-HumanHairDreads = Dreadlocks
accessory-HumanHairDrillruru = Drillruru
accessory-HumanHairDrillhairextended = Drill Hair (Extended)
accessory-HumanHairEmo = Emo
accessory-HumanHairEmofringe = Emo Fringe
accessory-HumanHairNofade = Fade (None)
accessory-HumanHairHighfade = Fade (High)
accessory-HumanHairMedfade = Fade (Medium)
accessory-HumanHairLowfade = Fade (Low)
accessory-HumanHairBaldfade = Fade (Bald)
accessory-HumanHairFeather = Feather
accessory-HumanHairFather = Father
accessory-HumanHairSargeant = Flat Top
accessory-HumanHairFlair = Flair
accessory-HumanHairBigflattop = Flat Top (Big)
accessory-HumanHairFlow = Flow Hair
accessory-HumanHairGelled = Gelled Back
accessory-HumanHairGentle = Gentle
accessory-HumanHairHalfbang = Half-banged Hair
accessory-HumanHairHalfbang2 = Half-banged Hair 2
accessory-HumanHairHalfshaved = Half-shaved
accessory-HumanHairHedgehog = Hedgehog Hair
accessory-HumanHairHimecut = Hime Cut
accessory-HumanHairHimecut2 = Hime Cut 2
accessory-HumanHairShorthime = Hime Cut (Short)
accessory-HumanHairHimeup = Hime Updo
accessory-HumanHairHitop = Hitop
accessory-HumanHairJade = Jade
accessory-HumanHairJensen = Jensen Hair
accessory-HumanHairJoestar = Joestar
accessory-HumanHairKeanu = Keanu Hair
accessory-HumanHairKusanagi = Kusanagi Hair
accessory-HumanHairLong = Long Hair 1
accessory-HumanHairLong2 = Long Hair 2
accessory-HumanHairLong3 = Long Hair 3
accessory-HumanHairLongovereye = Long Over Eye
accessory-HumanHairLbangs = Long Bangs
accessory-HumanHairLongemo = Long Emo
accessory-HumanHairLongfringe = Long Fringe
accessory-HumanHairLongsidepart = Long Side Part
accessory-HumanHairMegaeyebrows = Mega Eyebrows
accessory-HumanHairMessy = Messy
accessory-HumanHairModern = Modern
accessory-HumanHairMohawk = Mohawk
accessory-HumanHairNitori = Nitori
accessory-HumanHairReversemohawk = Mohawk (Reverse)
accessory-HumanHairUnshavenMohawk = Mohawk (Unshaven)
accessory-HumanHairMulder = Mulder
accessory-HumanHairOdango = Odango
accessory-HumanHairOmbre = Ombre
accessory-HumanHairOneshoulder = One Shoulder
accessory-HumanHairShortovereye = Over Eye
accessory-HumanHairOxton = Oxton
accessory-HumanHairParted = Parted
accessory-HumanHairPart = Parted (Side)
accessory-HumanHairKagami = Pigtails
accessory-HumanHairPigtails = Pigtails 2
accessory-HumanHairPigtails2 = Pigtails 3
accessory-HumanHairPixie = Pixie Cut
accessory-HumanHairPompadour = Pompadour
accessory-HumanHairBigpompadour = Pompadour (Big)
accessory-HumanHairPonytail = Ponytail
accessory-HumanHairPonytail2 = Ponytail 2
accessory-HumanHairPonytail3 = Ponytail 3
accessory-HumanHairPonytail4 = Ponytail 4
accessory-HumanHairPonytail5 = Ponytail 5
accessory-HumanHairPonytail6 = Ponytail 6
accessory-HumanHairPonytail7 = Ponytail 7
accessory-HumanHairHighponytail = Ponytail (High)
accessory-HumanHairStail = Ponytail (Short)
accessory-HumanHairLongstraightponytail = Ponytail (Long)
accessory-HumanHairCountry = Ponytail (Country)
accessory-HumanHairFringetail = Ponytail (Fringe)
accessory-HumanHairSidetail = Ponytail (Side)
accessory-HumanHairSidetail2 = Ponytail (Side) 2
accessory-HumanHairSidetail3 = Ponytail (Side) 3
accessory-HumanHairSidetail4 = Ponytail (Side) 4
accessory-HumanHairSpikyponytail = Ponytail (Spiky)
accessory-HumanHairPoofy = Poofy
accessory-HumanHairQuiff = Quiff
accessory-HumanHairRonin = Ronin
accessory-HumanHairShaved = Shaved
accessory-HumanHairShavedpart = Shaved Part
accessory-HumanHairShortbangs = Short Bangs
accessory-HumanHairA = Short Hair
accessory-HumanHairShorthair2 = Short Hair 2
accessory-HumanHairShorthair3 = Short Hair 3
accessory-HumanHairD = Short Hair 4
accessory-HumanHairE = Short Hair 5
accessory-HumanHairF = Short Hair 6
accessory-HumanHairShorthairg = Short Hair 7
accessory-HumanHair80s = Short Hair 80s
accessory-HumanHairRosa = Short Hair Rosa
accessory-HumanHairB = Shoulder-length Hair
accessory-HumanHairSidecut = Sidecut
accessory-HumanHairSkinhead = Skinhead
accessory-HumanHairProtagonist = Slightly Long Hair
accessory-HumanHairSpikey = Spiky
accessory-HumanHairSpiky = Spiky 2
accessory-HumanHairSpiky2 = Spiky 3
accessory-HumanHairSwept = Swept Back Hair
accessory-HumanHairSwept2 = Swept Back Hair 2
accessory-HumanHairThinning = Thinning
accessory-HumanHairThinningfront = Thinning (Front)
accessory-HumanHairThinningrear = Thinning (Rear)
accessory-HumanHairTopknot = Topknot
accessory-HumanHairTressshoulder = Tress Shoulder
accessory-HumanHairTrimmed = Trimmed
accessory-HumanHairTrimflat = Trim Flat
accessory-HumanHairTwintail = Twintails
accessory-HumanHairUndercut = Undercut
accessory-HumanHairUndercutleft = Undercut Left
accessory-HumanHairUndercutright = Undercut Right
accessory-HumanHairUnkept = Unkept
accessory-HumanHairUpdo = Updo
accessory-HumanHairVlong = Very Long Hair
accessory-HumanHairLongest = Very Long Hair 2
accessory-HumanHairLongest2 = Very Long Over Eye
accessory-HumanHairVeryshortovereyealternate = Very Short Over Eye
accessory-HumanHairVlongfringe = Very Long with Fringe
accessory-HumanHairVolaju = Volaju
accessory-HumanHairWisp = Wisp

View File

@@ -0,0 +1,5 @@
accessory-VoxFacialHairColonel = Vox Colonel
accessory-VoxFacialHairFu = Quill Fu
accessory-VoxFacialHairNeck = Neck Quills
accessory-VoxFacialHairBeard = Quill Beard
accessory-VoxFacialHairRuffBeard = Ruff Beard

View File

@@ -0,0 +1,13 @@
accessory-VoxHairShortQuills = Short Vox Quills
accessory-VoxHairKingly = Vox Kingly
accessory-VoxHairAfro = Vox Afro
accessory-VoxHairMohawk = Vox Mohawk
accessory-VoxHairYasuhiro = Vox Yasuhiro
accessory-VoxHairHorns = Vox Horns
accessory-VoxHairNights = Vox Nights
accessory-VoxHairSurf = Vox Surf
accessory-VoxHairCropped = Vox Cropped
accessory-VoxHairRuffhawk = Vox Ruffhawk
accessory-VoxHairRows = Vox Rows
accessory-VoxHairMange = Vox Mange
accessory-VoxHairPony = Vox Pony

View File

@@ -43,6 +43,21 @@
- /Audio/Voice/Human/femalescream_5.ogg - /Audio/Voice/Human/femalescream_5.ogg
wilhelm: /Audio/Voice/Human/wilhelm_scream.ogg wilhelm: /Audio/Voice/Human/wilhelm_scream.ogg
- type: action
actionType: VoxScream
icon: Interface/Actions/scream.png
name: "Scream"
filters:
- vox
behaviorType: Instant
behavior: !type:ScreamAction
cooldown: 10
male:
- /Audio/Voice/Vox/shriek1.ogg
female:
- /Audio/Voice/Vox/shriek1.ogg
wilhelm: /Audio/Voice/Human/wilhelm_scream.ogg
- type: action - type: action
actionType: GhostBoo actionType: GhostBoo
icon: Interface/Actions/scream.png icon: Interface/Actions/scream.png

View File

@@ -0,0 +1 @@


View File

@@ -0,0 +1,274 @@
# TODO: Add descriptions (many)
# TODO BODY: Part damage
- type: entity
id: PartVox
parent: BaseItem
name: "vox body part"
abstract: true
- type: entity
id: TorsoVox
name: "vox torso"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "torso_m"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "torso_m"
- type: BodyPart
partType: Torso
size: 14
compatibility: Biological
mechanisms:
- HeartHuman
- LungsHuman
- StomachHuman
- LiverHuman
- KidneysHuman
- type: BiologicalSurgeryData
- type: Damageable
# TODO BODY DettachableDamageableComponent?
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 100
# deadThreshold: 150
- type: entity
id: HeadVox
name: "vox head"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "head_m"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "head_m"
- type: BodyPart
partType: Head
size: 7
compatibility: Biological
vital: true
mechanisms:
- BrainHuman
- EyesHuman
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 50
# deadThreshold: 120
- type: Input
context: "ghost"
- type: DummyInputMover
- type: GhostOnMove
- type: entity
id: LeftArmVox
name: "left vox arm"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "l_arm"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "l_arm"
- type: BodyPart
partType: Arm
size: 5
compatibility: Biological
symmetry: Left
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 40
# deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity
id: RightArmVox
name: "right vox arm"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "r_arm"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "r_arm"
- type: BodyPart
partType: Arm
size: 5
compatibility: Biological
symmetry: Right
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 40
# deadThreshold: 80
- type: Extension
distance: 2.4
- type: entity
id: LeftHandVox
name: "left vox hand"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "l_hand"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "l_hand"
- type: BodyPart
partType: Hand
size: 3
compatibility: Biological
symmetry: Left
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 30
# deadThreshold: 60
- type: Grasp
- type: entity
id: RightHandVox
name: "right vox hand"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "r_hand"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "r_hand"
- type: BodyPart
partType: Hand
size: 3
compatibility: Biological
symmetry: Right
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 30
# deadThreshold: 60
- type: Grasp
- type: entity
id: LeftLegVox
name: "left vox leg"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "l_leg"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "l_leg"
- type: BodyPart
partType: Leg
size: 6
compatibility: Biological
symmetry: Left
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 45
# deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity
id: RightLegVox
name: "right vox leg"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "r_leg"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "r_leg"
- type: BodyPart
partType: Leg
size: 6
compatibility: Biological
symmetry: Right
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 45
# deadThreshold: 90
- type: Leg
speed: 2.6
- type: Extension
distance: 3.0
- type: entity
id: LeftFootVox
name: "left vox foot"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "l_foot"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "l_foot"
- type: BodyPart
partType: Foot
size: 2
compatibility: Biological
symmetry: Left
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 30
# deadThreshold: 60
- type: entity
id: RightFootVox
name: "right vox foot"
parent: PartVox
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Vox/parts.rsi
state: "r_foot"
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: "r_foot"
- type: BodyPart
partType: Foot
size: 2
compatibility: Biological
symmetry: Right
- type: BiologicalSurgeryData
- type: Damageable
damageContainer: biologicalDamageContainer
resistances: defaultResistances
# criticalThreshold: 30
# deadThreshold: 60

View File

@@ -0,0 +1,14 @@
- type: bodyPreset
name: "vox"
id: VoxPreset
partIDs:
head: HeadVox
torso: TorsoVox
right arm: RightArmVox
left arm: LeftArmVox
right hand: RightHandVox
left hand: LeftHandVox
right leg: RightLegVox
left leg: LeftLegVox
right foot: RightFootVox
left foot: LeftFootVox

View File

@@ -0,0 +1,23 @@
- type: entity
save: false
name: Vox
parent: BaseVox
id: Vox
components:
- type: Mind
showExamineInfo: true
- type: Input
context: "human"
- type: Alerts
- type: Actions
innateActions:
- VoxScream
- Disarm
- type: Eye
zoom: 0.5, 0.5
- type: CameraRecoil
- type: Examiner
- type: HumanInventoryController
- type: AiFactionTag
factions:
- NanoTrasen

View File

@@ -0,0 +1,109 @@
# SKREEEEEEEEEEE
- type: entity
parent: HumanMob_Content
abstract: True
id: BaseVox
components:
- type: Icon
sprite: Mobs/Species/Vox/parts.rsi
state: vox_m
- type: Sprite
netsync: false
noRot: true
drawdepth: Mobs
layers:
- map: [ "enum.HumanoidVisualLayers.Chest" ]
sprite: Mobs/Species/Vox/parts.rsi
state: torso_m
- map: [ "enum.HumanoidVisualLayers.Head" ]
sprite: Mobs/Species/Vox/parts.rsi
state: head_m
- map: [ "enum.HumanoidVisualLayers.Eyes" ]
color: "#008800"
sprite: Mobs/Customization/eyes.rsi
state: vox_eyes_s
- map: [ "enum.HumanoidVisualLayers.RArm" ]
sprite: Mobs/Species/Vox/parts.rsi
state: r_arm
- map: [ "enum.HumanoidVisualLayers.LArm" ]
sprite: Mobs/Species/Vox/parts.rsi
state: l_arm
- map: [ "enum.HumanoidVisualLayers.RLeg" ]
sprite: Mobs/Species/Vox/parts.rsi
state: r_leg
- map: [ "enum.HumanoidVisualLayers.LLeg" ]
sprite: Mobs/Species/Vox/parts.rsi
state: l_leg
# Vox don't have female clothing masks.
#- shader: StencilClear
# sprite: Mobs/Species/Vox/parts.rsi
# state: l_leg
#- shader: StencilMask
# map: [ "enum.HumanoidVisualLayers.StencilMask" ]
# sprite: Mobs/Customization/masking_helpers.rsi
# state: female_full
# visible: false
#- map: [ "enum.Slots.INNERCLOTHING" ]
# shader: StencilDraw
- map: [ "enum.HumanoidVisualLayers.LHand" ]
sprite: Mobs/Species/Vox/parts.rsi
state: l_hand
- map: [ "enum.HumanoidVisualLayers.RHand" ]
sprite: Mobs/Species/Vox/parts.rsi
state: r_hand
- map: [ "enum.HumanoidVisualLayers.LFoot" ]
sprite: Mobs/Species/Vox/parts.rsi
state: l_foot
- map: [ "enum.HumanoidVisualLayers.RFoot" ]
sprite: Mobs/Species/Vox/parts.rsi
state: r_foot
- map: [ "enum.HumanoidVisualLayers.Handcuffs" ]
color: "#ffffff"
sprite: Objects/Misc/handcuffs.rsi
state: body-overlay-2
visible: false
- map: [ "enum.Slots.IDCARD" ]
- map: [ "enum.Slots.GLOVES" ]
- map: [ "enum.Slots.SHOES" ]
- map: [ "enum.Slots.EARS" ]
- map: [ "enum.Slots.OUTERCLOTHING" ]
- map: [ "enum.Slots.EYES" ]
- map: [ "enum.Slots.BELT" ]
- map: [ "enum.Slots.NECK" ]
- map: [ "enum.Slots.BACKPACK" ]
- map: [ "enum.HumanoidVisualLayers.FacialHair" ]
state: shaved
sprite: Mobs/Customization/human_facial_hair.rsi
- map: [ "enum.HumanoidVisualLayers.Hair" ]
state: bald
sprite: Mobs/Customization/human_hair.rsi
- map: [ "enum.Slots.MASK" ]
- map: [ "enum.Slots.HEAD" ]
- type: Body
template: HumanoidTemplate
preset: VoxPreset
centerSlot: torso
- type: Metabolism
needsGases:
Nitrogen: 0.00060763888
producesGases:
Nitrogen: 0.00045572916
CarbonDioxide: 0.00015190972
# - type: Appearance
# visuals:
# - type: RotationVisualizer
# - type: BuckleVisualizer
# - type: FireVisualizer
# sprite: Mobs/Effects/onfire.rsi
# normalState: Generic_mob_burning
# alternateState: Standing
# fireStackAlternateState: 3
# - type: CreamPiedVisualizer
# state: creampie_human
- type: HumanoidAppearance
canColorHair: false
canColorFacialHair: false
categoriesHair: VoxHair
categoriesFacialHair: VoxFacialHair
- type: Inventory
speciesId: vox

View File

@@ -0,0 +1,19 @@
# Bald and shaved are used for multiple species.
- categories: [HumanHair, VoxHair]
id: HairBald
# Bald is always on top
priority: 1
sprite:
sprite: Mobs/Customization/human_hair.rsi
state: bald
type: spriteAccessory
- categories: [HumanFacialHair, VoxFacialHair]
id: FacialHairShaved
# Shaved is always on top
priority: 1
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: shaved
type: spriteAccessory

View File

@@ -0,0 +1,210 @@
- categories: HumanFacialHair
id: HumanFacialHairAbe
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: abe
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairBrokenman
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: brokenman
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairChin
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: chin
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairDwarf
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: dwarf
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairFullbeard
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: fullbeard
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairCroppedfullbeard
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: croppedfullbeard
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairGt
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: gt
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairHip
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: hip
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairJensen
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: jensen
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairNeckbeard
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: neckbeard
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairWise
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: wise
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairMuttonmus
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: muttonmus
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairMartialartist
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: martialartist
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairChinlessbeard
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: chinlessbeard
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairMoonshiner
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: moonshiner
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairLongbeard
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: longbeard
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairVolaju
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: volaju
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHair3oclock
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: 3oclock
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairFiveoclock
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: fiveoclock
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHair5oclockmoustache
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: 5oclockmoustache
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHair7oclock
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: 7oclock
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHair7oclockmoustache
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: 7oclockmoustache
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairMoustache
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: moustache
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairPencilstache
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: pencilstache
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairSmallstache
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: smallstache
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairWalrus
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: walrus
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairFumanchu
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: fumanchu
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairHogan
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: hogan
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairSelleck
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: selleck
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairChaplin
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: chaplin
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairVandyke
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: vandyke
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairWatson
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: watson
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairElvis
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: elvis
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairMutton
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: mutton
type: spriteAccessory
- categories: HumanFacialHair
id: HumanFacialHairSideburn
sprite:
sprite: Mobs/Customization/human_facial_hair.rsi
state: sideburn
type: spriteAccessory

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
- type: spriteAccessory
id: VoxFacialHairColonel
categories: VoxFacialHair
sprite:
sprite: Mobs/Customization/vox_facial_hair.rsi
state: vox_colonel_s
- type: spriteAccessory
id: VoxFacialHairFu
categories: VoxFacialHair
sprite:
sprite: Mobs/Customization/vox_facial_hair.rsi
state: vox_fu_s
- type: spriteAccessory
id: VoxFacialHairNeck
categories: VoxFacialHair
sprite:
sprite: Mobs/Customization/vox_facial_hair.rsi
state: vox_neck_s
- type: spriteAccessory
id: VoxFacialHairBeard
categories: VoxFacialHair
sprite:
sprite: Mobs/Customization/vox_facial_hair.rsi
state: vox_beard_s
- type: spriteAccessory
id: VoxFacialHairRuffBeard
categories: VoxFacialHair
sprite:
sprite: Mobs/Customization/vox_facial_hair.rsi
state: vox_ruff_beard_s

View File

@@ -0,0 +1,91 @@
- type: spriteAccessory
id: VoxHairShortQuills
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_shortquills_s
- type: spriteAccessory
id: VoxHairKingly
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_kingly_s
- type: spriteAccessory
id: VoxHairAfro
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_afro_s
- type: spriteAccessory
id: VoxHairMohawk
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_mohawk_s
- type: spriteAccessory
id: VoxHairYasuhiro
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_yasu_s
- type: spriteAccessory
id: VoxHairHorns
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_horns_s
- type: spriteAccessory
id: VoxHairNights
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_nights_s
- type: spriteAccessory
id: VoxHairSurf
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_surf_s
- type: spriteAccessory
id: VoxHairCropped
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_cropped_s
- type: spriteAccessory
id: VoxHairRuffhawk
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_ruff_hawk_s
- type: spriteAccessory
id: VoxHairRows
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_rows_s
- type: spriteAccessory
id: VoxHairMange
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_mange_s
- type: spriteAccessory
id: VoxHairPony
categories: VoxHair
sprite:
sprite: Mobs/Customization/vox_hair.rsi
state: vox_pony_s

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

View File

@@ -1,26 +1 @@
{ {"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, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
"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
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

View File

@@ -1,26 +1 @@
{ {"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-MASK", "directions": 4}, {"name": "inhand-left", "directions": 4}, {"name": "inhand-right", "directions": 4}, {"name": "equipped-MASK-vox", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
"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-MASK",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

View File

@@ -1,26 +1 @@
{ {"version": 1, "license": "CC-BY-SA-3.0", "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/7e4e9d432d88981fb9bb463970c5b98ce85c0abe", "size": {"x": 32, "y": 32}, "states": [{"name": "icon"}, {"name": "equipped-FEET", "directions": 4}, {"name": "inhand-left", "directions": 4}, {"name": "inhand-right", "directions": 4}, {"name": "equipped-FEET-vox", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/7e4e9d432d88981fb9bb463970c5b98ce85c0abe",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "equipped-FEET",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,26 +1 @@
{ {"version": 1, "license": "CC-BY-SA-3.0", "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", "size": {"x": 32, "y": 32}, "states": [{"name": "icon"}, {"name": "equipped-INNERCLOTHING", "directions": 4}, {"name": "inhand-left", "directions": 4}, {"name": "inhand-right", "directions": 4}, {"name": "equipped-INNERCLOTHING-vox", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "equipped-INNERCLOTHING",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}

View File

@@ -1 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "eyes", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]} {"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "eyes", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_eyes_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

View File

@@ -0,0 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/vgstation-coders/vgstation13/blob/02ff588d59b3c560c685d9ca75e882d32a72d8cb/icons/mob/human_face.dmi", "states": [{"name": "vox_beard_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_colonel_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_fu_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_neck_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_ruff_beard_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_ruff_beard_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

View File

@@ -0,0 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/vgstation-coders/vgstation13/blob/02ff588d59b3c560c685d9ca75e882d32a72d8cb/icons/mob/human_face.dmi", "states": [{"name": "vox_afro_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_afro_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_bald_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_cropped_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_cropped_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_horns_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_horns_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_kingly_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_kingly_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_mange_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_mange_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_mohawk_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_mohawk_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_nights_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_nights_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_pony_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_pony_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_rows_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_rows_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_ruff_hawk_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_ruff_hawk_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_shortquills_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_shortquills_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_surf_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_surf_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_yasu_s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_yasu_s2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

View File

@@ -0,0 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/vgstation-coders/vgstation13 at 02ff588d59b3c560c685d9ca75e882d32a72d8cb", "states": [{"name": "groin_f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "groin_m", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "head_f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "head_m", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "l_arm", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "l_foot", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "l_hand", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "l_leg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "overlay_husk", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "r_arm", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "r_foot", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "r_hand", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "r_leg", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "torso_f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "torso_m", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "vox_m", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Some files were not shown because too many files have changed in this diff Show More