From 3af2928a25c4cbc0ee6e8edabf317d060b652b06 Mon Sep 17 00:00:00 2001 From: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:15:04 +0100 Subject: [PATCH] Add nose customization to humans & dwarves (#25557) Initial commit --- .../Clothing/EntitySystems/ClothingSystem.cs | 55 ++++++++++++++++-- Resources/Locale/en-US/markings/noses.ftl | 14 +++++ .../Clothing/Head/base_clothinghead.yml | 2 + .../Clothing/Head/hardsuit-helmets.yml | 3 + .../Entities/Clothing/Masks/bandanas.yml | 3 + .../Entities/Clothing/Masks/masks.yml | 33 +++++++++++ .../Entities/Clothing/Masks/specific.yml | 5 +- .../Customization/Markings/human_noses.yml | 54 +++++++++++++++++ Resources/Prototypes/Species/human.yml | 4 ++ Resources/Prototypes/tags.yml | 3 + .../Customization/human_noses.rsi/blob.png | Bin 0 -> 15567 bytes .../Customization/human_noses.rsi/droop.png | Bin 0 -> 15529 bytes .../Customization/human_noses.rsi/meta.json | 31 ++++++++++ .../Customization/human_noses.rsi/nubby.png | Bin 0 -> 15526 bytes .../Customization/human_noses.rsi/schnozz.png | Bin 0 -> 15586 bytes .../Customization/human_noses.rsi/uppie.png | Bin 0 -> 15515 bytes 16 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 Resources/Locale/en-US/markings/noses.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/blob.png create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/droop.png create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/nubby.png create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/schnozz.png create mode 100644 Resources/Textures/Mobs/Customization/human_noses.rsi/uppie.png diff --git a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs index 154171fc05..50a1d93a6c 100644 --- a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Tag; using Robust.Shared.GameStates; +using System.Linq; namespace Content.Shared.Clothing.EntitySystems; @@ -22,6 +23,9 @@ public abstract class ClothingSystem : EntitySystem [ValidatePrototypeId] private const string HairTag = "HidesHair"; + [ValidatePrototypeId] + private const string NoseTag = "HidesNose"; + public override void Initialize() { base.Initialize(); @@ -85,18 +89,57 @@ public abstract class ClothingSystem : EntitySystem } } + private void ToggleVisualLayer(EntityUid equipee, HumanoidVisualLayers layer, string tag) + { + InventorySystem.InventorySlotEnumerator enumerator = _invSystem.GetSlotEnumerator(equipee); + bool shouldLayerShow = true; + + while (enumerator.NextItem(out EntityUid item)) + { + if (_tagSystem.HasTag(item, tag)) + { + if (tag == NoseTag) //Special check needs to be made for NoseTag, due to masks being toggleable + { + if (TryComp(item, out MaskComponent? mask) && TryComp(item, out ClothingComponent? clothing)) + { + if (clothing.EquippedPrefix != mask.EquippedPrefix) + { + shouldLayerShow = false; + break; + } + } + else + { + shouldLayerShow = false; + break; + } + } + else + { + shouldLayerShow = false; + break; + } + } + } + _humanoidSystem.SetLayerVisibility(equipee, layer, shouldLayerShow); + } + protected virtual void OnGotEquipped(EntityUid uid, ClothingComponent component, GotEquippedEvent args) { component.InSlot = args.Slot; - if (args.Slot == "head" && _tagSystem.HasTag(args.Equipment, HairTag)) - _humanoidSystem.SetLayerVisibility(args.Equipee, HumanoidVisualLayers.Hair, false); + if ((new string[] { "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, HairTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag); + if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag); } protected virtual void OnGotUnequipped(EntityUid uid, ClothingComponent component, GotUnequippedEvent args) { component.InSlot = null; - if (args.Slot == "head" && _tagSystem.HasTag(args.Equipment, HairTag)) - _humanoidSystem.SetLayerVisibility(args.Equipee, HumanoidVisualLayers.Hair, true); + if ((new string[] { "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, HairTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag); + if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag)) + ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag); } private void OnGetState(EntityUid uid, ClothingComponent component, ref ComponentGetState args) @@ -113,8 +156,8 @@ public abstract class ClothingSystem : EntitySystem private void OnMaskToggled(Entity ent, ref ItemMaskToggledEvent args) { //TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix - if(args.equippedPrefix != null) - SetEquippedPrefix(ent, args.IsToggled ? args.equippedPrefix : null, ent); + SetEquippedPrefix(ent, args.IsToggled ? args.equippedPrefix : null, ent); + ToggleVisualLayer(args.Wearer, HumanoidVisualLayers.Snout, NoseTag); } private void OnEquipDoAfter(Entity ent, ref ClothingEquipDoAfterEvent args) diff --git a/Resources/Locale/en-US/markings/noses.ftl b/Resources/Locale/en-US/markings/noses.ftl new file mode 100644 index 0000000000..e49d87d559 --- /dev/null +++ b/Resources/Locale/en-US/markings/noses.ftl @@ -0,0 +1,14 @@ +marking-HumanNoseSchnozz = Schnozz +marking-HumanNoseSchnozz-schnozz = Nose + +marking-HumanNoseNubby = Nubby Nose +marking-HumanNoseNubby-nubby = Nose + +marking-HumanNoseDroop = Droopy Nose +marking-HumanNoseDroop-droop = Nose + +marking-HumanNoseBlob = Blobby Nose +marking-HumanNoseBlob-blob = Nose + +marking-HumanNoseUppie = Uppie Nose +marking-HumanNoseUppie-uppie = Nose diff --git a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml index 2d2d11524f..d13b284ff2 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml @@ -136,6 +136,7 @@ - HidesHair - WhitelistChameleon - HelmetEVA + - HidesNose - type: IdentityBlocker - type: entity @@ -174,6 +175,7 @@ tags: - HidesHair - WhitelistChameleon + - HidesNose - type: IdentityBlocker - type: entity diff --git a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml index 358fc81c8b..25f641b1c4 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml @@ -17,6 +17,9 @@ sprite: Clothing/Head/Hardsuits/basic.rsi - type: Clothing sprite: Clothing/Head/Hardsuits/basic.rsi + - type: Tag + tags: + - HidesNose #Atmospherics Hardsuit - type: entity diff --git a/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml b/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml index c008a755ee..2d65e67982 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/bandanas.yml @@ -22,6 +22,9 @@ - state: icon map: ["foldedLayer"] visible: false + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBandanaBase diff --git a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml index 77655e7cdb..0b388aee6b 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml @@ -16,6 +16,7 @@ - MonkeyWearable - HamsterWearable - WhitelistChameleon + - HidesNose - type: entity parent: ClothingMaskGas @@ -195,6 +196,7 @@ tags: - ClownMask - WhitelistChameleon + - HidesNose - type: entity parent: ClothingMaskClownBase @@ -205,6 +207,7 @@ - ClownMask - HamsterWearable - WhitelistChameleon + - HidesNose - type: entity parent: ClothingMaskClown @@ -231,6 +234,9 @@ sprite: Clothing/Mask/joy.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -248,6 +254,7 @@ tags: - HamsterWearable - WhitelistChameleon + - HidesNose - type: entity parent: ClothingMaskPullableBase @@ -298,6 +305,9 @@ - type: BreathMask - type: IngestionBlocker - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskClownBase @@ -326,7 +336,9 @@ sprite: Clothing/Mask/swat.rsi - type: Tag tags: + - WhitelistChameleon - HidesHair + - HidesNose - type: entity parent: ClothingMaskGasExplorer @@ -351,7 +363,9 @@ sprite: Clothing/Mask/ert.rsi - type: Tag tags: + - WhitelistChameleon - HidesHair + - HidesNose - type: entity parent: ClothingMaskGasERT @@ -386,6 +400,7 @@ tags: - HamsterWearable - WhitelistChameleon + - HidesNose - type: IdentityBlocker - type: entity @@ -400,6 +415,9 @@ sprite: Clothing/Mask/fox.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -413,6 +431,9 @@ sprite: Clothing/Mask/bee.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -426,6 +447,9 @@ sprite: Clothing/Mask/bear.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -439,6 +463,9 @@ sprite: Clothing/Mask/raven.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -452,6 +479,9 @@ sprite: Clothing/Mask/jackal.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase @@ -465,6 +495,9 @@ sprite: Clothing/Mask/bat.rsi - type: BreathMask - type: IdentityBlocker + - type: Tag + tags: + - HidesNose - type: entity parent: ClothingMaskBase diff --git a/Resources/Prototypes/Entities/Clothing/Masks/specific.yml b/Resources/Prototypes/Entities/Clothing/Masks/specific.yml index e60c29d212..1e85073da9 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/specific.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity parent: ClothingMaskBase id: ClothingMaskGasChameleon name: gas mask @@ -6,7 +6,8 @@ suffix: Chameleon components: - type: Tag - tags: [] # ignore "WhitelistChameleon" tag + tags: # ignore "WhitelistChameleon" tag + - HidesNose - type: Sprite sprite: Clothing/Mask/gas.rsi - type: Clothing diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml new file mode 100644 index 0000000000..51fc2fd15a --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Customization/Markings/human_noses.yml @@ -0,0 +1,54 @@ +- type: marking + id: HumanNoseSchnozz + bodyPart: Snout + markingCategory: Snout + followSkinColor: true + forcedColoring: true + speciesRestriction: [Human, Dwarf] + sprites: + - sprite: Mobs/Customization/human_noses.rsi + state: schnozz + +- type: marking + id: HumanNoseNubby + bodyPart: Snout + markingCategory: Snout + followSkinColor: true + forcedColoring: true + speciesRestriction: [Human, Dwarf] + sprites: + - sprite: Mobs/Customization/human_noses.rsi + state: nubby + +- type: marking + id: HumanNoseDroop + bodyPart: Snout + markingCategory: Snout + followSkinColor: true + forcedColoring: true + speciesRestriction: [Human, Dwarf] + sprites: + - sprite: Mobs/Customization/human_noses.rsi + state: droop + +- type: marking + id: HumanNoseBlob + bodyPart: Snout + markingCategory: Snout + followSkinColor: true + forcedColoring: true + speciesRestriction: [Human, Dwarf] + sprites: + - sprite: Mobs/Customization/human_noses.rsi + state: blob + +- type: marking + id: HumanNoseUppie + bodyPart: Snout + markingCategory: Snout + followSkinColor: true + forcedColoring: true + speciesRestriction: [Human, Dwarf] + sprites: + - sprite: Mobs/Customization/human_noses.rsi + state: uppie diff --git a/Resources/Prototypes/Species/human.yml b/Resources/Prototypes/Species/human.yml index 979e226c81..0cbd9cc03f 100644 --- a/Resources/Prototypes/Species/human.yml +++ b/Resources/Prototypes/Species/human.yml @@ -20,6 +20,7 @@ Head: MobHumanHead Hair: MobHumanoidAnyMarking FacialHair: MobHumanoidAnyMarking + Snout: MobHumanoidAnyMarking Chest: MobHumanTorso Eyes: MobHumanoidEyes LArm: MobHumanLArm @@ -40,6 +41,9 @@ FacialHair: points: 1 required: false + Snout: + points: 1 + required: false Tail: # the cat tail joke points: 0 required: false diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 6e13da6a9a..e2d08042b5 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -653,6 +653,9 @@ - type: Tag id: HidesHair # for headwear. +- type: Tag + id: HidesNose # for non-standard noses. + - type: Tag id: HighRiskItem diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/blob.png b/Resources/Textures/Mobs/Customization/human_noses.rsi/blob.png new file mode 100644 index 0000000000000000000000000000000000000000..31774b81f96644384812103c48efae3d4bb224cf GIT binary patch literal 15567 zcmeI3Pl()99LJv&|E*LDJ^1GorxvU=lRuN0?4+4#*PX4q=(Njpw7aWfGs&Bs(3vDn zGCQ;DL9v$#o_df{y$KaX3R;R_K~X76kya4|d+?;CR;35=P>QTC$^6N_nR%?WBFYO) zlHdEi@9!m_-+RAg4tZsE&*K}%9vA}vY@C@cl+bZk@VnzSw13Au^gTM<=}gai0Nk}X z_}v1Izi}S`JC2#mzG+)b5Lc_%O+S}N1OxT9&V4nU-awYuVTUMkZO!3?B+m^K8G29SG~If5X@<_h zI&478_mEB)s&i_#Z+kU+#E?Dr$bnH#ipAd8L$9~d7&^4)Pc0z?9i&5*UU}JpTnT!1 z)79bB61tTw!|vWUtNrAxi4=H7UOQ}?BV>Uml7&+t%8-igRhe|5=G$)Bw(I$5md$n% zGLw_xtYRMCZ(4@k^0uiQF6rmH9}N~XALd0~lvrM5MWHP6iXbY|_;y}Ucs>>+>WRfD z+J;$OUK>L!^Jqe+6(JRm5$lP^Kl=(1owrEzENsDYn*0U_1kuUSxakBka@N$XJr&$O0kucQDLi!_Py zO>#8XgTac+CAv$lSHyZXD$s;0SJCvKn&tIiK|n+0*0lC7tEcS9%)tb%k8%`0CLcXU zs|GF7f{H?gy+#M|?5f|=TsX0a=EQo|dK7i73=gkzLG`bj|3D%J~7%BL*T&x@VWu;!R5c-x5{#rx2UIm~C$=~P=in!o>41$K}Y`$xZaek@;X=iVFimHYqMLAIwW}VL-?x#YN_Wc_}Uo2-&2#$b2v_#f1SO zn-mwB59Xz~Fd$@;;v)0Gyc8D(gltk=WImXe;=+KCO^S=m2lG-~7!a~aagq68UWy9? zLNSzLJNIk+d?1HZa%&6Hu?~k(WgsA09LjF@X}!buC1cuPXIJ|0InPWKsg4$ zz4p=P&+bNj-qg%@9c=&jGM|Nf=?^HqM~o(I#RYxM5+Q|F&J z@zM4951Loby!%^eX|>e2wEdYMw_f=0*Rv;;&sM?Irs3j8&Y@3}S64TH7h2DKGI#3Q Q<)GWl)Skl0#}2&wCjxNP)c^nh literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/droop.png b/Resources/Textures/Mobs/Customization/human_noses.rsi/droop.png new file mode 100644 index 0000000000000000000000000000000000000000..57bed8e5bd82455235a9bed3f1a9775d6580d17b GIT binary patch literal 15529 zcmeI3O^n+_6vqcDp|W(v0YNJc$V!C-0>__O$8M6cY_{x5q%7N1-96Fqc$~GG*skqu zvWpM}F7(O)A;bl#0>lA{6XHYSfH-mKrI#MKgOE5QK+D+9hj)^UR;37m#!?c$dGr3y z^P8Dx=inO~=U-S{czgi>u(-a~+$6uxrJv&uknc~ut3Q&T2g9}P7=VW!Nk8|2_dhrV zz?qM{_ExghdeK5buMC~Q#^pgTB)tKsogIV_UBQW9 zbi}Hcc9JBtB&px;m-|{dh&qyDnx-VHlB$ZNhZyhq2^@%id^#5y=`?YSA}>t5z!y?o zXa~DVy;MpQjgR5Ddf_;c9}n3PiqZgvl2VqXSwRjO$Ar64H@h?kNw|x9*iT{-r_78C zcY-8{cY--7$L_g_$(*!Wc^x7VAQI!;!v5d=e|Gb7{nUWlbl90$7*!mHQFP)^Sp zed4*3$vLEydgfj`9(Z%YQcoV1ErooBYGka|N`zq&MC~BxHu6=rF+wP;tYoW7cN~0Axp1XHgLv71M zqhe`hQKQh4)*$=GfeAd4O0jQ2$3d1GL_L@^ydLaeDfBxvY0_BeIbK!PO3)1=a#^^c z)udU?g{W+$S?hkBKp)}tW`i`8JRWvJ_Le8M>nufV#U^j!< zY8At$q?-ZSO?L~C&I^kZAR<4xEK{$jF48s8kzJX{V=USx(nQxFlV@mETTzWsqJr2| zqL(6%)IHcO^hw9!kYom|K&%)t(KHRwHb^pCb8OMIZ5z2dLW(mU%M6*RRBK*LR_k72 z6_d4`RkjQG>fzRrqw8fADuhvt)BRU3jW*!8q>U?98k6l~3!=2PHBh=euv3!`wN5T; z961d0rl<302y*>G`1~CG9qhBVS1y(HnlBOuZqkPlUha?;a+IB)s~!%c2sUp#>7z+8)u~;>h9MREjSBF*IKr$Xp^IcDaX{qX{Lj8NwFj>WD z2l^fCG^EkUMh*X^nLAoNyz31#eQ)_6%v`<`57)#|DW9&Pwe+#VBK4Ql0+`i3r6x_a zP1a1_e=Dt{-QBD|xnqz+Qqu2XXwglFZnHy+ZaQ=ldC~WhhC0kfH5a1NXP^AWe1SZs zY2Ba$93{g zK^p&6m@2H}`_H{RnT+UOs#01!2?d00a$Iaal$Yb8fUr%Di_M4fa$FP;w#jj^`A}Yt zivq$nIW9II%FA(4K-eb7#pXkKIW7ta+vK>|d?+u+MFC-(92c7p<>k02AZ(N4V)LQA z92W(IZE{>}K9rZ^qJXeXj*HEQ@^V}h5Vpy2vH4J5j*9}qHaRXfAIi&dQ9#%x$HnGD zc{wf$2;1bi*nB82$3+2Qn;aLL59Q^!C?IT;<6`rnyc`z=gl%$MY(A8i7A7y>VxPQm+b6Hqe)I0lC&+8L0$ST_0kHoh0N39F z;I{+v`x5}WG5|kc2Ecj`fRn*HuY7-w^nGo;x!fMy`Q?tX2;}3d%b&b%v~IUg+`je3 zjaTnKRffNBUsS$)^t)rE>k*H}SDh~wA3o!M{Nc@$vqP?%b>cWUI0pWB?8Kj+|M2$9 PX}|T=^Ucqmzx?K3i<`72 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/meta.json b/Resources/Textures/Mobs/Customization/human_noses.rsi/meta.json new file mode 100644 index 0000000000..af67414763 --- /dev/null +++ b/Resources/Textures/Mobs/Customization/human_noses.rsi/meta.json @@ -0,0 +1,31 @@ +{ + "version":1, + "size": { + "x":32, + "y":32 + }, + "copyright":"Created by SlamBamActionman", + "license":"CC-BY-SA-3.0", + "states": [ + { + "name":"schnozz", + "directions":4 + }, + { + "name":"blob", + "directions":4 + }, + { + "name":"droop", + "directions":4 + }, + { + "name":"uppie", + "directions":4 + }, + { + "name":"nubby", + "directions":4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/nubby.png b/Resources/Textures/Mobs/Customization/human_noses.rsi/nubby.png new file mode 100644 index 0000000000000000000000000000000000000000..ab5bdde977010d2cf9c0f2f40d0d9c526694fb26 GIT binary patch literal 15526 zcmeI3&yU+g6vwARLaEcp zZnAqo{E$!);!99~(juaWah$>+X%$@drT`Jc$?{$Tk`1i%B2CZ9v# zqmQ2e;KhsX`ewY@IAL0Tw}5QFi3|O1K%xPt9P0nYsUKCurDsJcv zxe+Ylw!6F=;?uh)*R9=iR@oMh)#fUFlO*Wk7zzDu$BWEEXtBvG&R}ORAF$4wK?*u655Wr zRzE)Ij#yQ(9mjzQVXxOK^oj*PY(b@5E<;&`sw$BPDcbR3)R(;INS0)nr;Z~lbc5LS zJt4`9n*LT?6~&~Z(J{ELZZPV|iw5inMc79HR0=YjCbF%OCfEu)>CkKo;tuX&FOG;# znW_uge(XnWe@2%h_sovToHQDvzNe12+nw5V6fbQP1Ouc~mC^c6fZ-aB{H@T!OWWj9 zj!e7y*mcH}voBNPnK^dccW1~FPbN#3LN-Gca;@fKh*9i^>%QNqWvgs;h)`HuOjnig z+=lDfelL2y0%^&3zQ@^c9mTk&%Bm*Gs-!CGs%$E%sg;h(iYd#vBv~Ytqv6}Gvoj?} zQ8#5ZpCcDZ=OFvXMlm{2mV9h3k8PQbA9hh(bGxX8Vc@kYaNL-S9IYyI(eL;n85XV; zD{xwKPL-}SbH$5dPMC!V4Z6&*9klH4x4WuKi7_#ITWkYHjT2X3}gp$*2HZ4c9EX8()sdMs))Tct1 zR65kj#U!KuyIo94Gtt$u84>&NY#hRI{3uYzS;u;J()Jutv&(%$=OTgHg`%=j5~d=(VxO+E7`lG-`H|$amr% z3h_dVtcio{^(^at8J)fYlj`4b|AC2!(Dt28gJR2NO(|KDqZsO7b9KlKM+(0ZQwhQh^g~<294TZzgrLvz5jhs!R^3B;NyR-c3u-u%&r7EgdUg z_1w6o4tk@SbE@QNC%YA&CJ*MgHm~bNy#ncGTCwW(ac8scl6z*9+zIBjfrfTW6`q+T z%sB?aY^rjP&}sF|TFC=C`ELM6e-0)J>*)S-H-C(;=x%1Ea`8?mAZ(N4V)LQA92W(I zZE{>}K9rZ^qJXeXj*HEQ@^V}h5Vpy2vH4J5j*9}qHaRXfAIi&dQ9#%x$HnGDc{wf$ z2;1bi*nB82$3+2Qn;aLL59Q^!C?IT;<6`rnyc`z=gl%$MY(A8ip+m*b*}{d70Mv z;gb)@i@1Wdyw(6<_gMhmdKZ8{ZjKhSaM$LQ*f-@d+f t?S}OG>!)sQ6w7d?&L#r`w{PDA-hS<|uU5W$YA=agSvpz2^zzwv{sN7~y8{3K literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/schnozz.png b/Resources/Textures/Mobs/Customization/human_noses.rsi/schnozz.png new file mode 100644 index 0000000000000000000000000000000000000000..618c5f5eb73a9c298e7594755f604e64c65fd93b GIT binary patch literal 15586 zcmeI3TZr6L7{^bswz{=iP}GWO$Ra2;lgnf#GwIBf7Y{3gE^(1r4o|!qUwj#<2 z%;h`Z`TtMyJLi1KJj|1$BloWDyQL2Ruy%MTKZZUx2d}GEq4!tJJzt@ZtDT`q4}dk- z2d@=i;qc7>Y&>L+Pxups`&8Yo#5BV$!dR{1pxyvvHq{(WpMgG8gj1%KWq&ySCd-&c zmfevk2nA;VPMbsXF5EspGOo|h=xKx9lq=#Z_5QWr=AVY_1P| z%eY2K9m{WR42PmDJMH_9%JbD~HCBzsYt|Uu7^rnLuB+m-2C}>cJ4BJMX$~*O1iqWd&|4a3)-8vpX6QUD z!wR%~59!3NI%nGUZExD{F=Q*3^W0(0>>&#>by>I+>NAu<*QySz!d1oGxx=&!yXxJQ;c-cOzT0jvulX=136jhS5+{k{lAwx`DyKFGqACaxlX_3g zqhK3mX|9V$Tv8K4)FaXp_dxr{(0pxKF44XbA46A5wp-EsoLSMPAn#aH8NS^Z>DgLU z>VRFgU36M77tiqBnj@-krK!V~=WCV@hx0kq5Hn3f)r+O1k(QGjEQ*kWx-4-iDVgSy zNnO;_QbI)85MrSam3LU@ZGAS_Ee&e}Su0vXgQ6mEB_*wJMMaKt#kf)AO2uMPFUh(t z8l|RnMBZV&%{5V_)5?)P!P)=SA-dRf3^inWXnoE_)-77SVJ+JZ_bhE~Cdy`5lN`It?w- zhN@eIy?UE?cFC`5F5EJO*2Hr5dfj!Y47bnlLG>@2|G-3e+TKf>2GJ1GvY67jQbG~Y zn+&;>k~BC&E|z31B`dlBo74Qary;FMQnM!gd(+Tf#rm{nO+h2aH?OSO@L!s_GNeq6(gN>bK(U=)oN3l8Hn-k>T-XTrq0aV0j{M zqI;$n+zFC$LxU%}3MYFBBZ-EvK2?!N=&*X$ThRkL`fb3sejIcZ*4F*!a(-!F(dBf- zyyzep5OPRyk@;X*iVFim4k<1&A1q68VL-?s#YN_WWhpKU2sxy<$b7IY#f1SOhZGl? z50<64Fd*cR;v)0GvJ@8vgd9>_WIkAy;=+KCLyC*c2g_1i7!Yzuagq68S&9n-LJlb| zG9N5UabZBnA;m@JgJmf$3R-To@2?NO6(*U|EU_140fdE;1i1OL1X9$RWi==7VJ^E({1c zB;x98|J@c^=s&hq^k>=)&s{i%{)o%yLt_O1=I;Pt-(vv$dJ%n|17KDF;Je)bsD}W! z$$sX+cekRxCx-J|#%rg)|NQl}?=b7G{GfmE*bVF7{&?brPZs6d_V0h{n~zd!@<-1c z_<40|&o+m-Uy5%%)xYXGqy)bo-nH|m(ayu>xDDd zI%|SHJrCj5&F8;Z`0ePfH$HoKXPjL;1>nN7{E2h#-+tu1SD$|C!&>_Id6_?Z@cFY3 oeYtLBSDSs0F0KIJ;>9b#%a0_ldGW`u7lLlXgCqIZ?%BQnPd6LjBLDyZ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Customization/human_noses.rsi/uppie.png b/Resources/Textures/Mobs/Customization/human_noses.rsi/uppie.png new file mode 100644 index 0000000000000000000000000000000000000000..a1be557443960f7759222fd5bd3e152cda39a4eb GIT binary patch literal 15515 zcmeI3&yU+g6vqcDP+7VX5<*m*tW+Q>aQq`qoR}nKn{3&YNLhAMb@xP_@nmCdV!O6? zlU;;Z;M5BTP8H%0KpYBEPly8t#GOkI6p0fO0wFjegwQg!^TYd+jFwV_Kw~L!-n{pH zGycrXvvcr`waYIpE5L#Sasjt)Xi_z!w!}R+j`}()^^oX~z6(IEJsuF1A`{$k6ykZ`AxS&BLo zHXCa~&Gm_p&lW^17j!`{WtF_HYx?toDl2(O&Ph30RC9(V8=5K%k4$xe{wn)c+gPt( z8g@smN~RNro*_y7em~pKWnF(;Qc9(gB&(9DiZntD_MOlih)!@WNixb)Cjs_tFSK1p zi1L~(cQ>qLGEqn4V|ZOXZ`_d+4B1hN(!lg2B`Zs_L>3-vyj{N=56!|7>5?9C!hq_O znL4lIhHlVt=X5!C&+VAbNux3Dd**n1y_sDH;qo3uFhn|288r7jBCV6a-Ssh9-lLat zZr0U@c6%~8$1+8pxnm~-dyXvfB(iuZBr{Z|*J{*!Vur5Yblq+>S!HV@ghH(ruPWi$ ztF~jg{os6Af|AL6PqLA^8Ir0htC}dQqN+4i*-%tND?TSHhAgL&B#|IT!?o=8{_z}Y zQ>F{LWaJC!9H~f{gYF;849yc|Nyn!0SlDR0e$Nc6cF)`htQ^Yh=?Od;!Qp93AuPgLRBVti6 zSfZu1+L~F^bS#t6G~e?ylnhlJ)uexK8YZh4cT8uSSXF6sWuu1w(#)N#0^aimn!cO- z4`wdeiN|Z=sFY9F&~o%3VbJ>ud6aWBqjPDO4DvA z-C|4AZYZ57uQ+yCRfoNS=9DUW+DUH38}z}PR15ihE?<^lGgPeE1Jd2B+w`6pM0bLM zHq=1JOySl%VahQSCR3GqgpR9c(n=rD>3;)h{O4e*u#WFP_w&c(itcAtkc)Q$fUr%D zi_HgkIW7Q%ZE{>}KETUy0U&IX<6`pxUXBX@VVfKmn-B1ETmT5$HaRXfAK>M<01&pxak2RTFUJLduuYDO%?EfnE&zmWa$Iaaz{_y~AZ(N4 zV)FrBjtc-`n;aLL5Abqa00`UUxY&Gvm*WCJ*e1ut<^#MO7XZRGIW9II;N`dg5Vpy2 zvH1Wm#|40}O^%Dr2Y5Ly0EBIFTx>qT%W(l9Y?I?+^8sFt3jkr8Ok4|-*KLVI-?8n} zmuY`3eD@H25m&$~>kWhso<`{K9fW>6qURqF+LaOd@ft$LO@y9w-+S%LOEmV4)%sF% zaQCOX$|90aFE4%grrx;IJagx(w{E=t;MuJC`_>iZ(