From 075eb0d982ac7507169b5bb9f33e94bb7795c596 Mon Sep 17 00:00:00 2001 From: EmoGarbage404 <98561806+EmoGarbage404@users.noreply.github.com> Date: Thu, 12 May 2022 19:35:55 -0400 Subject: [PATCH] The Newest Furry Race [Skeletons] (#7825) Co-authored-by: Moony Co-authored-by: Kara Co-authored-by: metalgearsloth --- Content.Client/Entry/IgnoredComponents.cs | 1 + .../UI/HumanoidProfileEditor.xaml.cs | 29 ++ .../Body/Components/BodyComponent.cs | 42 ++- .../Components/BodyReassembleComponent.cs | 35 ++ .../Body/Systems/BodyReassembleSystem.cs | 234 ++++++++++++ Content.Server/Cloning/CloningSystem.cs | 2 +- .../Body/Components/SharedBodyComponent.cs | 6 +- .../Body/Part/BodyPartCompatibility.cs | 4 +- Content.Shared/Species/SpeciesPrototype.cs | 1 + Resources/Audio/Effects/bone_rattle.ogg | Bin 0 -> 19244 bytes Resources/Audio/Effects/license.txt | 27 -- Resources/Audio/Effects/licenses.txt | 30 ++ Resources/Audio/Voice/Skeleton/license.txt | 1 + .../Audio/Voice/Skeleton/skeleton_scream.ogg | Bin 0 -> 10137 bytes .../Locale/en-US/body/behavior/reassemble.ftl | 4 + Resources/Prototypes/Body/Parts/skeleton.yml | 231 ++++++++++++ .../Prototypes/Body/Presets/skeleton.yml | 14 + Resources/Prototypes/Damage/modifier_sets.yml | 14 + .../Entities/Mobs/Player/skeleton.yml | 28 ++ .../Entities/Mobs/Species/skeleton.yml | 352 ++++++++++++++++++ Resources/Prototypes/species.yml | 9 +- .../Mobs/Species/Skeleton/parts.rsi/full.png | Bin 0 -> 6363 bytes .../Species/Skeleton/parts.rsi/head_f.png | Bin 0 -> 793 bytes .../Species/Skeleton/parts.rsi/head_m.png | Bin 0 -> 793 bytes .../Mobs/Species/Skeleton/parts.rsi/l_arm.png | Bin 0 -> 226 bytes .../Species/Skeleton/parts.rsi/l_foot.png | Bin 0 -> 651 bytes .../Species/Skeleton/parts.rsi/l_hand.png | Bin 0 -> 629 bytes .../Mobs/Species/Skeleton/parts.rsi/l_leg.png | Bin 0 -> 336 bytes .../Mobs/Species/Skeleton/parts.rsi/meta.json | 66 ++++ .../Mobs/Species/Skeleton/parts.rsi/r_arm.png | Bin 0 -> 628 bytes .../Species/Skeleton/parts.rsi/r_foot.png | Bin 0 -> 656 bytes .../Species/Skeleton/parts.rsi/r_hand.png | Bin 0 -> 640 bytes .../Mobs/Species/Skeleton/parts.rsi/r_leg.png | Bin 0 -> 317 bytes .../Species/Skeleton/parts.rsi/skull_icon.png | Bin 0 -> 870 bytes .../Species/Skeleton/parts.rsi/torso_f.png | Bin 0 -> 1030 bytes .../Species/Skeleton/parts.rsi/torso_m.png | Bin 0 -> 1058 bytes 36 files changed, 1093 insertions(+), 37 deletions(-) create mode 100644 Content.Server/Body/Components/BodyReassembleComponent.cs create mode 100644 Content.Server/Body/Systems/BodyReassembleSystem.cs create mode 100644 Resources/Audio/Effects/bone_rattle.ogg delete mode 100644 Resources/Audio/Effects/license.txt create mode 100644 Resources/Audio/Voice/Skeleton/license.txt create mode 100644 Resources/Audio/Voice/Skeleton/skeleton_scream.ogg create mode 100644 Resources/Locale/en-US/body/behavior/reassemble.ftl create mode 100644 Resources/Prototypes/Body/Parts/skeleton.yml create mode 100644 Resources/Prototypes/Body/Presets/skeleton.yml create mode 100644 Resources/Prototypes/Entities/Mobs/Player/skeleton.yml create mode 100644 Resources/Prototypes/Entities/Mobs/Species/skeleton.yml create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/full.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_f.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_m.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_arm.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_foot.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_hand.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_leg.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/r_arm.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/r_foot.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/r_hand.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/r_leg.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/skull_icon.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_f.png create mode 100644 Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_m.png diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index c052a17946..2f4117bc1e 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -346,6 +346,7 @@ namespace Content.Client.Entry "DoorRemote", "InteractionPopup", "HealthAnalyzer", + "BodyReassemble", "Thirst", "CanEscapeInventory", "PowerSink", diff --git a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs index 690b995b5e..46936b7a56 100644 --- a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs @@ -541,6 +541,23 @@ namespace Content.Client.Preferences.UI Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color)); break; } + case SpeciesSkinColor.TintedHues: + { + if (!_rgbSkinColorContainer.Visible) + { + _skinColor.Visible = false; + _rgbSkinColorContainer.Visible = true; + } + + // a little hacky in order to convert rgb --> hsv --> rgb + var color = new Color(_rgbSkinColorSelector.Color.R, _rgbSkinColorSelector.Color.G, _rgbSkinColorSelector.Color.B); + var newColor = Color.ToHsv(color); + newColor.Y = .1f; + color = Color.FromHsv(newColor); + + Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color)); + break; + } } IsDirty = true; @@ -753,6 +770,18 @@ namespace Content.Client.Preferences.UI _rgbSkinColorContainer.Visible = true; } + // set the RGB values to the direct values otherwise + _rgbSkinColorSelector.Color = Profile.Appearance.SkinColor; + break; + } + case SpeciesSkinColor.TintedHues: + { + if (!_rgbSkinColorContainer.Visible) + { + _skinColor.Visible = false; + _rgbSkinColorContainer.Visible = true; + } + // set the RGB values to the direct values otherwise _rgbSkinColorSelector.Color = Profile.Appearance.SkinColor; break; diff --git a/Content.Server/Body/Components/BodyComponent.cs b/Content.Server/Body/Components/BodyComponent.cs index f41a11cabc..695e651f81 100644 --- a/Content.Server/Body/Components/BodyComponent.cs +++ b/Content.Server/Body/Components/BodyComponent.cs @@ -83,11 +83,20 @@ namespace Content.Server.Body.Components } } - public override void Gib(bool gibParts = false) + public override HashSet Gib(bool gibParts = false) { - base.Gib(gibParts); + var gibs = base.Gib(gibParts); - SoundSystem.Play(Filter.Pvs(Owner), _gibSound.GetSound(), _entMan.GetComponent(Owner).Coordinates, AudioHelpers.WithVariation(0.025f)); + var xform = _entMan.GetComponent(Owner); + var coordinates = xform.Coordinates; + + // These have already been forcefully removed from containers so run it here. + foreach (var part in gibs) + { + _entMan.EventBus.RaiseLocalEvent(part, new PartGibbedEvent(Owner, gibs)); + } + + SoundSystem.Play(Filter.Pvs(Owner, entityManager: _entMan), _gibSound.GetSound(), coordinates, AudioHelpers.WithVariation(0.025f)); if (_entMan.TryGetComponent(Owner, out ContainerManagerComponent? container)) { @@ -96,18 +105,41 @@ namespace Content.Server.Body.Components foreach (var ent in cont.ContainedEntities) { cont.ForceRemove(ent); - _entMan.GetComponent(ent).Coordinates = _entMan.GetComponent(Owner).Coordinates; + _entMan.GetComponent(ent).Coordinates = coordinates; ent.RandomOffset(0.25f); } } } - _entMan.EventBus.RaiseLocalEvent(Owner, new BeingGibbedEvent(), false); + _entMan.EventBus.RaiseLocalEvent(Owner, new BeingGibbedEvent(gibs), false); _entMan.QueueDeleteEntity(Owner); + + return gibs; } } public sealed class BeingGibbedEvent : EntityEventArgs { + public readonly HashSet GibbedParts; + + public BeingGibbedEvent(HashSet gibbedParts) + { + GibbedParts = gibbedParts; + } + } + + /// + /// An event raised on all the parts of an entity when it's gibbed + /// + public sealed class PartGibbedEvent : EntityEventArgs + { + public EntityUid EntityToGib; + public readonly HashSet GibbedParts; + + public PartGibbedEvent(EntityUid entityToGib, HashSet gibbedParts) + { + EntityToGib = entityToGib; + GibbedParts = gibbedParts; + } } } diff --git a/Content.Server/Body/Components/BodyReassembleComponent.cs b/Content.Server/Body/Components/BodyReassembleComponent.cs new file mode 100644 index 0000000000..cefe87d089 --- /dev/null +++ b/Content.Server/Body/Components/BodyReassembleComponent.cs @@ -0,0 +1,35 @@ +using System.Threading; +using Content.Server.Cloning; +using Content.Shared.Actions.ActionTypes; + +namespace Content.Server.Body.Components +{ + [RegisterComponent] + public sealed class BodyReassembleComponent : Component + { + /// + /// The dna entry used for reassembling the skeleton + /// updated before the entity is gibbed. + /// + [ViewVariables] + public ClonerDNAEntry? DNA = null; + + /// + /// The default time it takes to reassemble itself + /// + [ViewVariables] + [DataField("delay")] + public float DoAfterTime = 5f; + + /// + /// The list of body parts that are needed for reassembly + /// + [ViewVariables] + public HashSet? BodyParts = null; + + [DataField("action")] + public InstantAction? ReassembleAction = null; + + public CancellationTokenSource? CancelToken = null; + } +} diff --git a/Content.Server/Body/Systems/BodyReassembleSystem.cs b/Content.Server/Body/Systems/BodyReassembleSystem.cs new file mode 100644 index 0000000000..439cc89dab --- /dev/null +++ b/Content.Server/Body/Systems/BodyReassembleSystem.cs @@ -0,0 +1,234 @@ +using System.Threading; +using Content.Server.Body.Components; +using Content.Server.Cloning; +using Content.Server.DoAfter; +using Content.Server.Mind.Components; +using Content.Server.Popups; +using Content.Server.Preferences.Managers; +using Content.Shared.Actions; +using Content.Shared.CharacterAppearance.Systems; +using Content.Shared.Preferences; +using Content.Shared.Species; +using Content.Shared.Verbs; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +/// +/// Fair warning, this is all kinda shitcode, but it'll have to wait for a major +/// refactor until proper body systems get added. The current implementation is +/// definitely not ideal and probably will be prone to weird bugs. +/// + +namespace Content.Server.Body.Systems +{ + public sealed class BodyReassembleSystem : EntitySystem + { + [Dependency] private readonly IServerPreferencesManager _prefsManager = null!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedHumanoidAppearanceSystem _humanoidAppearance = default!; + + private const float SelfReassembleMultiplier = 2f; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPartGibbed); + SubscribeLocalEvent(StartReassemblyAction); + + SubscribeLocalEvent>(AddReassembleVerbs); + SubscribeLocalEvent(ReassembleComplete); + SubscribeLocalEvent(ReassembleCancelled); + } + + private void StartReassemblyAction(EntityUid uid, BodyReassembleComponent component, ReassembleActionEvent args) + { + args.Handled = true; + StartReassembly(uid, component, SelfReassembleMultiplier); + } + + private void ReassembleCancelled(EntityUid uid, BodyReassembleComponent component, ReassembleCancelledEvent args) + { + component.CancelToken = null; + } + + private void OnPartGibbed(EntityUid uid, BodyReassembleComponent component, PartGibbedEvent args) + { + if (!TryComp(args.EntityToGib, out var mindComp) || mindComp?.Mind == null) + return; + + component.BodyParts = args.GibbedParts; + UpdateDNAEntry(uid, args.EntityToGib); + mindComp.Mind.TransferTo(uid); + + if (component.ReassembleAction == null) + return; + + _actions.AddAction(uid, component.ReassembleAction, null); + } + + private void StartReassembly(EntityUid uid, BodyReassembleComponent component, float multiplier = 1f) + { + if (component.CancelToken != null) + return; + + if (!GetNearbyParts(uid, component, out var partList)) + return; + + if (partList == null) + return; + + var doAfterTime = component.DoAfterTime * multiplier; + var cancelToken = new CancellationTokenSource(); + component.CancelToken = cancelToken; + + var doAfterEventArgs = new DoAfterEventArgs(component.Owner, doAfterTime, cancelToken.Token, component.Owner) + { + BreakOnTargetMove = true, + BreakOnUserMove = true, + BreakOnDamage = true, + BreakOnStun = true, + NeedHand = false, + TargetCancelledEvent = new ReassembleCancelledEvent(), + TargetFinishedEvent = new ReassembleCompleteEvent(uid, uid, partList), + }; + + _doAfterSystem.DoAfter(doAfterEventArgs); + } + + /// + /// Adds the custom verb for reassembling body parts + /// + private void AddReassembleVerbs(EntityUid uid, BodyReassembleComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (!TryComp(uid, out var mind) || + !mind.HasMind || + component.CancelToken != null) + return; + + // doubles the time if you reconstruct yourself + var multiplier = args.User == uid ? SelfReassembleMultiplier : 1f; + + // Custom verb + AlternativeVerb custom = new() + { + Text = Loc.GetString("reassemble-action"), + Act = () => + { + StartReassembly(uid, component, multiplier); + }, + IconEntity = uid, + Priority = 1 + }; + args.Verbs.Add(custom); + } + + private bool GetNearbyParts(EntityUid uid, BodyReassembleComponent component, out HashSet? partList) + { + partList = new HashSet(); + + if (component.BodyParts == null) + return false; + + // Ensures all of the old body part pieces are there + var xformQuery = GetEntityQuery(); + var notFound = true; + var bodyXform = xformQuery.GetComponent(uid); + + foreach (var part in component.BodyParts) + { + if (!xformQuery.TryGetComponent(part, out var xform) || + !bodyXform.Coordinates.InRange(EntityManager, xform.Coordinates, 2f)) continue; + + notFound = false; + partList.Add(part); + } + + if (notFound) + { + _popupSystem.PopupEntity(Loc.GetString("reassemble-fail"), uid, Filter.Entities(uid)); + return false; + } + + return true; + } + + private void ReassembleComplete(EntityUid uid, BodyReassembleComponent component, ReassembleCompleteEvent args) + { + component.CancelToken = null; + + if (component.DNA == null) + return; + + // Creates the new entity and transfers the mind component + var speciesProto = _prototype.Index(component.DNA.Value.Profile.Species).Prototype; + var mob = EntityManager.SpawnEntity(speciesProto, EntityManager.GetComponent(component.Owner).MapPosition); + + _humanoidAppearance.UpdateFromProfile(mob, component.DNA.Value.Profile); + MetaData(mob).EntityName = component.DNA.Value.Profile.Name; + + if (TryComp(uid, out var mindcomp) && mindcomp.Mind != null) + mindcomp.Mind.TransferTo(mob); + + // Cleans up all the body part pieces + foreach (var entity in args.PartList) + { + EntityManager.DeleteEntity(entity); + } + + _popupSystem.PopupEntity(Loc.GetString("reassemble-success", ("user", mob)), mob, Filter.Entities(mob)); + } + + /// + /// Called before the skeleton entity is gibbed in order to save + /// the dna for reassembly later + /// + /// the entity that the player will transfer to + /// the entity whose DNA is being saved + private void UpdateDNAEntry(EntityUid uid, EntityUid body) + { + if (!TryComp(uid, out var skelBodyComp) || !TryComp(body, out var mindcomp)) + return; + + if (mindcomp.Mind == null) + return; + + if (mindcomp.Mind.UserId == null) + return; + + var profile = (HumanoidCharacterProfile) _prefsManager.GetPreferences(mindcomp.Mind.UserId.Value).SelectedCharacter; + skelBodyComp.DNA = new ClonerDNAEntry(mindcomp.Mind, profile); + } + + private sealed class ReassembleCompleteEvent : EntityEventArgs + { + /// + /// The entity being reassembled + /// + public readonly EntityUid Uid; + + /// + /// The user performing the reassembly + /// + public readonly EntityUid User; + public readonly HashSet PartList; + + public ReassembleCompleteEvent(EntityUid uid, EntityUid user, HashSet partList) + { + Uid = uid; + User = user; + PartList = partList; + } + } + + private sealed class ReassembleCancelledEvent : EntityEventArgs {} + } +} + +public sealed class ReassembleActionEvent : InstantActionEvent { } diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 381094f4d2..dc56b6738e 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -137,7 +137,7 @@ namespace Content.Server.Cloning // For example, GameTicker should be using this, and this should be using ICharacterProfile rather than HumanoidCharacterProfile. // It should carry a reference or copy of itself with the mobs that it affects. // See TODO in MedicalScannerComponent. - struct ClonerDNAEntry { + public struct ClonerDNAEntry { public Mind.Mind Mind; public HumanoidCharacterProfile Profile; diff --git a/Content.Shared/Body/Components/SharedBodyComponent.cs b/Content.Shared/Body/Components/SharedBodyComponent.cs index a73fdf620c..9598784484 100644 --- a/Content.Shared/Body/Components/SharedBodyComponent.cs +++ b/Content.Shared/Body/Components/SharedBodyComponent.cs @@ -394,15 +394,19 @@ namespace Content.Shared.Body.Components } } - public virtual void Gib(bool gibParts = false) + public virtual HashSet Gib(bool gibParts = false) { + var gibs = new HashSet(); foreach (var part in SlotParts.Keys) { + gibs.Add(part.Owner); RemovePart(part); if (gibParts) part.Gib(); } + + return gibs; } } diff --git a/Content.Shared/Body/Part/BodyPartCompatibility.cs b/Content.Shared/Body/Part/BodyPartCompatibility.cs index 91a24819cf..1af9d20148 100644 --- a/Content.Shared/Body/Part/BodyPartCompatibility.cs +++ b/Content.Shared/Body/Part/BodyPartCompatibility.cs @@ -1,4 +1,4 @@ -using System; +using System; using Content.Shared.Body.Components; using Robust.Shared.Serialization; @@ -14,6 +14,6 @@ namespace Content.Shared.Body.Part Universal = 0, Biological, Mechanical, - Slime + Slime, } } diff --git a/Content.Shared/Species/SpeciesPrototype.cs b/Content.Shared/Species/SpeciesPrototype.cs index fd0fab0dda..e4221c75d6 100644 --- a/Content.Shared/Species/SpeciesPrototype.cs +++ b/Content.Shared/Species/SpeciesPrototype.cs @@ -49,4 +49,5 @@ public enum SpeciesSkinColor { HumanToned, Hues, + TintedHues, //This gives a color tint to a humanoid's skin (10% saturation with full hue range). } diff --git a/Resources/Audio/Effects/bone_rattle.ogg b/Resources/Audio/Effects/bone_rattle.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a4f25ff2cd49806f8cc8666117c20af6808e1351 GIT binary patch literal 19244 zcmagF1yo(VwkW)CcPUUPE*p2Jr8pZa?oiy_wUpvk+})kxZl$=pLvg3Yz5JVg=iGb# z``);3jgXO*nar7~dnPL=n3*X9(7?YQhj;%pCI%8Jq255b+Bq6pIK6a1iIx9rh#S=3 zMiZ36%gq0JUS_^PpoxShFvXt#f6pMyKZrOXa19H4b7locGcs!nL$$x?$)w5HS=m`x zd008g=#)&1U5qSj&B(-UT`e5#Y;86=FJOF?N{OFLP@^+;y$N0<$ zXrmmn`7Gpli^ved6o2v|eZQhHvMsDDw6YxoQ6r*h!a=wKgr&#>ag|;w!w~Wy0!S51 z>^MMPl_KTe+ipg1pz|B$Y3LIj1WZVD{RHmhb-*$%Jk?KH-> zm;SE`=`SB-khO@w6B=WRAikgv0Tm`YLQws~78&3NVH1#y!IiGY9j+!GoupDYXH>-D zn&c2yR*_SMJTAKGt|s%YF7vKFn#qCMO+K1Uf!Yg!x;KFa1VR5Qw?6APFXb=mWKcjh zC12teD3^jLcatv{CLpLB8Zdql2^mr>1t>O8y3o|J(ju+FysW`yxQ21K2KDa{h;m_H zRs&>Pq!#`k#Z)uVfv=(~ex~PD1lea`O;Tyh!AKe?I@U z7YHNd8K#Mreux~=27krk2SH1agD8sn4<*QekeqF@)QQxKQ9kt4o$M0awCV0pl{DJs zlH|0%8nhlG+=A#5G?dbtoidT?G$xIjTJTTH13L|&qGSrvN4S@c-bZKv8D}w-icqqs z0hy~gk-A&lj0>=E?_Xw7qL)6_&9?!W5xSIS)r_PIY26v8pN=BE^!-os z5r*i^V1b}7!=KD23f>TxypTNZjq_LZxNNooQ2v|9C<$=Mmk&yWv<1%oe>o=ufB?+D zR{ZbkuPOgy#rd&e^h0#DBkaSBFI9QZ82{0?9!ybGHi#87azU&(vVJ$ysgh61s-S*O zi=iN12@ERu$D<%hB{PnG4^Q~lNrI9chd@OTulP^J{iYhnBANV;GJZy^h)oSClk7~& z973ups_L#bnn^Cpje)ugF6;9?>+_NNuY&%kVf~lq01&4M`0JDLh7oN2>0jhUkp5Bd zzdgqRw?Bq>FosH|hDvUVarB&1;evA#M_iFpP8m;k63=BC-$a>Pcbdy&TGeFM)nu{3 zM7z;Pv*BM3^N-uC&%6AG=e)QG1z*&bR4nX&drmf8)Fy8frF1NnW-N_IqFHEaNlNBH zNiOpL@Er57qU5lmkg&awD7w%@i_p~4=3MKc%A=P5XZbJBk#wYj6o}`DJ5v3J=X9|V zi$c7qhEeX~A0CA!Ap&(4fAyaV0D!J&RGGhVL{W)pR*7p?iAhyO=zsSZ2y~WHZkiJ! z*aQF|1OQ5ik^?Zq9HT{Sg)|V^cB$ZU_~3JX5Cjxqa-i~|Q8-7xrxj|7N)0APr!gbWIdR~iHDMk@`m z?GP)0`HIq&$M_IQ0*2V&GrnMg3W$}*K>fr4Bky<8zf8QR0|2rvD9E1(9jCE4fJqDd zw5J-6`&Ox9q^NBwCb2hrk|3W2)`xh0r>U;y2 zqO+=^s)?qGs-~-n=8dZQoR16ysw}sNr>feZx_D)yn&`9Ptg5SSvUsDaiSMgDAGmSt zvqA8Jd4ARf0yUU3F=%vIr?W`4u*@wkO{FU>Eh%lVDXpx~&fPD~Egh;cE3GUas;Mfg zv_67BD~n5O7)whT%WBFWN*RwDic4E6hHAd0RhAt!{6gtrJZiBot*k7oIevk*R2=m= z9JR1|7lMWh%MM#gT3T$6S{z0iY>4wp4?F0GzkeI5`E}I7Qs+XhsOqvBue+rV;loDX zEmQj@u*OE9v*KY0f?(>FZ`_W!88WTb_BEuh?}Fi-0dG`+St?|ur4?zVWk)r(3_ayX zB8sX$x(O!hJi3~%Y}a|BwC5vpOAlMDfo z?u z+)Et)0c=SgKSSR~rV=GRkRFE(HV4H|DIw$(d;nYJ#Lp>NRTs_}o{;6^gDsfir?f0f z`ew8uu#7O-_wtR$q>&2hUH}kOd)fKuBH)62Tp2Kv+6csu^QPWQmE>b9OPAC`P!;6k z%YfM$aJ6mO=7=FP^0Bq0L4CN&HcWk~lzn6nRD&;=4;)5q$Aeh7eS-N)eD5+Sbj5iIxyRs#19U?vj%= z*Y%86`3nsh$S;J`*XAoVNYwFz0fhaKOtN1>$cx*)4^bMEw!m~8;iE?q8R4TXag-GS zfmBD{BU0Co@qs|Sb9{)@1^6=bOucGWAP|HLCP?1#*KOhDLVKZ*(KL|&F^CuUkwM}P zJYfOBmkEM=Tq8`10s@F$3UG}evL$dr7ojIK8hcL%3itq~2L)n+rKt-bnJzLhB%iaM zh}R&7Ea;y&@)6Y#l`V+OS%sY*D?k=ZTk;tq(FzxcDHQaMXjxX&EeIo41kSO`P(w_? zwBkpy76SkrLl$)WH;zyP(FlMrK^}xIpBbj%2;V+2CnPcw2cXmUrGG&eLBxYB1M*un z!Uw4^MIZo3zL)a_QWeBcy#SQJ2V{^wP=WIcAYKU>0O;)@8PPXIV<-QZY)H(620UJ3 zCYTQ)Ctd>7M;0He1R)1usl*W#BD-F-7eKt$F&V@(thrnBrk{vh4F<)Oms-1 z*OLrcF+52?5NJO?0HU58Q7|7JHN;9lAc*-uJUU(roZ_UUL{D9i_!2s1w7^Ud+z8YK zb4r#FD*T8Abu%xd7T!yN3g)!JnIJ9)hP)a^a0MwrhV(8Nmb2wgDM9>`z^EMJKw4Ii zrCTw9>gNn2>LK!nM2I=VaIQHm6yT?=J>Vzx%^@fuzxMm&&%e4Rha}q~f2IAhF;If& zBKyT!$i=`At9r2!@&Je${^<*d{;xhv{=I)p3t~`v|BQ?OAoAC=5OW}XAQFg?(fw^v zLt04xByfL?F#sEq%Ed!4|I-(b4WaQjy^B|Ru}Fw$UI2eh^=}J_{6$=U2b2FZ_azsE zm?+Fk6sFv#${V7v=G^!W^TB)o4EUh}fWw025om6JtT#O%Q6?bT5z~+vODT*`vf4z7 zu$N#qo~-~^S;=ZY-7rE?A;SpF)>9s@2BwSgpK>g(cO8LjEy)l8R!nk^&%#i+1OpI4 z0k9w-`&-upn+`1OHa0slDsq2-)071afEh4=8WW;{ij7nHIoFUM(9roffZ&H38Ce&O zvd`WHr@P`p7C;6|9?}bi8}0W6$JTulO`)k9iC??`{hysM6z~QBV$sMbC{p>N(7$3t zW5!^`V#ndcL(CTdenRrJG~O$l>@{)#QPdw7u94s8AzEPP^7w4fc#zz-VO-y&(pvAILFmrOcue>7i7MV*#z zUun3`ukosJs0(k7C)Bq?t(+iJ09v4G4@DSmyduSPiNZ|FA4OCryb2dtYprqzWC>hE zVMELF1}5)$YIc7@0V+g7W&KVTEI4t#`o_SKWl?LzL2+eS{bqw#&T|6-pStgj5T@?Y z@qBhK+NqS5-oteYJRtbTxeXjGJ;@p%wGPbTIc28qX=Z7aIcy5LB^=Er1SPD*TZ)d| z2g$fFEgvlw8W^iWY4M`&!1m~TJgPWYwrVsWh`Rf1D)`yK+NX0HTZ_8OjKa+}QM%lD z*uDJCXhiL5%yPjSxPEp~TaqFx=x%NTOj>3hW9j5a9jFwQ2G z?7TM|29glrc{W%{3>{2f$Rx3SiOjKiR4e(+UV4yX-^*o)~Td>{LU zNTF#dcu;|0Rv{)td$@1PC8+3k`G+@Hep3i{t%DPy!OdSU} zcU`gwq#ei2oc#&^TpsFC@kY>jzphhH&8+!uHk06JbQX|&_FJb_$jd{x?mS@d!U@-cStO)TT->w8%-11y>*G#|SN32n` z)OmsIL|4QZfyT)XwIc_b<#{tcHxz z1ths;F|m5)#ypC!*lZ*=%;fPrFDmOdYwp>Tc!d0iY~(t^P1O)l^TLV3Rb8JFzN8Sn z{+QqKJBfpvijt4Arium^v7sw1?QGBR^O6GY8y=NxsEzO-;C=%Dp>!L+I6m@sP*B5G_x?n+0D{)VI_@tYLx8VRvEy?e-z^n~vpVz9=~oz1&0_s3%*nOgp1d=;wv3jc9U*KfyGLmA zJuI~0P>bvgVU}6M(p~aT$~O|KRiDqk5nE@WFZblb;VPE+JP|&b?Z_|Rg=m2yHf@f5 zt-GT$BHY|MMmli1CDtG#p@HoP-A=(EptX$jhByB$bS?~>=sTU0uiRFKuVI$zjCEBL zHShhjvEMET=?)eJuV=2H5+^#dBz~kZ<|w! zMq(>EwFO8-fEjecFRc*4*h?H`q99L;rIXl*S5XGXlo}Iudo#v%?>jllZYr7l4qks1 zv^mRiTrIYmZTBxW-;)!N*F***|Fj~+%~!Lo(p^zD%wch2<*_yV0PSDzwE86lg{-2w z1%m{#86v%ju7&^fv`>FUY`=0RY}d^lM*6_6$2*hvqszt+b!5~I*%@Y$j&(@-GH*@` z5oO@~HX`-x&-29m!O5$O>nY+7LXWfvq_t&t9?FzATg|klyo$B5>WM+Q=^&yc`4x)$ zK->Nu?yvAyxp-god=G6|+Y<3yTl6vUAvxU@i^oi&w}d;tSL3l@L%RyJQnE1eCvC%{ zKepKFIZ`1unqiXJY~A|rp7eOD%W-x0JMZhzvzx6nQ4rWJL3 zCN3VNezquON5LW+R^OB7op0gTe8#ZbBLq`cqOpr1C9ACHBoX;=9)@DQ`RVsZUV7J(0z7$%=`VS8aL*1w z+romHyl*j;RM=Ut^r_RG*lbQMf(4kqOUNIFF$0eq&JyD?)nAHJzEb$f*d}=2@*12E zGP*AdP}#w?$fRBjqE;9d;mZI&cIb#S`rs%>QlPrFl7+&y-E)V0AC7B%ywDXAWE^;u z#~7Tz_b9-R4NgRM18goIU#5>L-aj*D!5K{wKFka0!Icik4G$(ZLJfrZ2Mx%_8)D`Z z4tThQ@o55*NWAEU7h5GXXHwi6W)f@VOas!l@2%H%EdsB7kbkVU(KQ|GyBmCi;`Qgl zvhN!`ELVx%_?!UyON6CICcZ6BNJ(H>Pzvi4%<%^AC_8p)lVWlykksbRH7HlUuU6{R zYRc4T;`j(<<)RwPyddqY1JoT{qH2(bGg@RBGur1!MPwn3QfpW@<;x_Jj)d`PJ0~Ru zwY@QzgmT_NZgLRCMglp=H^SuCqW|1oyB-S&tBH6J$^I#YQn5BvSETBl;!T?Q96b~E z1Ap8FpgR9{*+o!9R`h2WeoES%=53Ki`B^jEh7rfTm)^1?$mmwvh1Q2c2i2KjweRhx zW|$=&v4M>Nq`JP-MmMoGLUv`0kAu*%V$HdgZE9kp!fWQ~NqSWySH#{j~Qyf}HF`*bb8Vjgay;gZ>dW6CFd zX!mL*vv;Bu4HgtOqlq_KM45t{lo-thk;yB*H>#E~MD^J;EbMngpO7xga&E*1(Cx~r zQKr}O?2p;g(lIxUpyNRIu(`(tSAiDEnkDMrR{U~De9Qeba6YR&u>%;dY%Eq|&>359 zvNwl25CJ{jc-~w>0pQZ3Hp&qFHN0}94Pj>;HyDca!lz|P`A9wO$*_9yn>W{k)~Yrd zw|d^8_YiRn63!M?#_Z~mg%ZP6!eshLobX1!rz4ezQQ4=lK!tvTW2#{F$zqr82cqBW z?#s%I+WC%pdB|JQvo#+zUD;}Kdyyk=hY1|nnBKTW^RAAAt3n&}W+kn1M`FaOCG+}7Z=-A{D$FJz*N_sqoSVnn#`9yV88s@*Rt9mR zGKG6;wH_kyhsRjNKNTq+_31ViI~vokT1oRdZojUkt3PdSH0%5cvZFuq+O8AuQl1(i zXIo(l|-WqC^QAopRK*JSd4qBt!DI{R>!;K9K zkMd?z{*DpGwTs8H4vGdcGTgX!=sSj+Uu1hvSo-PvQuLE+7F7z?_U(R8{Yky|edRSR zMNw&kX%;XjiFBgam|mvePrmIFm4=G7DkpSLfSs7aK7JFnj7H656@}(HJlhJN&BGBc z$ZnRrkeEsZfK0y2K|d#RF}!-xu?Ep)agq-RGF>+ zF`WL@wlOnidFS0NRZqx--big<5n^*Gc*UU_qte1|AduT9R1d>4(K}w1Mor!r`$QKD zI~E_;NUApq^K44(YE)W3#n8fWECuSCE(jiQj&`v95PsA!gGTQ?WMbIKy3&qYO zsg{LK_F3~Nq;Fz*(m^%!!W#xq^T6$c67)m%@w&1|*6ShO!s|i5h=%t+n1b3UCCZx^ z0hXN_S5P}nwOyT-^sSgM-m%cu5(XzVonMXpW@h-(Su!eI+STeN5^Igwp&LS%a!0-E zwdX_mt#K)`dj`>@g!DWmkNpGOZ|iE#eVX>C`-la?oVr|e`?6}vPHJyn z>ol6xT=<^SK*{0rnv)Ljj`)`iHGcP0CMy>Xjs`c zrbcIGAZ^xFdNy{B`N=s35ae`$j+TX!V`GAYlbeyAk%OIc9(D;6mTKX10b`}zLs#+b zMdxFjw8h?v%h?%~8{=Ff18=IOuDV`R(hipInE4(=zpEP*P4r44$kqYmTs zlTT;jSD|@6W@^%J(VIP6T9&@&iEaQf{IFbKFf9C|3k$%gcVe-dEJGpYbhhb=gfx9l z&DK0T>?r@~aF~)Zv9ht1Xb%D4L=QJ}#mEVDSci+Q{Nu)%5pmz%IsPzex#`a2t!!`q z8c*j~m1f6salA)@iJ=n)V7zzbo}3|pa!j}R8uIb#*DgxL1jK+Ty?mck!ET!8k_|p#n#P+lo!n*v(_U;(7NpdJdv$7YuL5i3nw2iH8`L zM2e(tF^vQL>DITJdGn;&f;;morI;mwm!tLLl-3dAkK{2&Ia|^%@+vc5S)0o`7X5ps6BzhaQDMgZK1VFTvqaVK4!R*nnt7u0m+`F zx#wufeN^88G5z&VwByA`Bzcd!hqhTfjnah?xCA=iztatOkMl{LRCIxXQnwtgO^P*t-+tDrgiU!>M_@N(s&o2@+7nz zoLT&MJFm7b$6RkMqTPlmP|t-Ez7Kq(QQAjDe|wOv`n`5U$gNiiS<%G3xKI-YKdQgj zNY64K>R!6C};7rPo4W)i67O;B*LqtMD*W%ab}}1Lzgy_XPuXNm%ov7 zx|yr0l-tfOB8W}plNyS$(7i?Oq4Oi^L#xSX&V4n~r6pD4!S34)%U9&t#TM@vvy_`( z6fHv+mP&LWLU^l%j7QQ$<*2}BA~l)c z*{C%_K?+DqNRL~deAG~Hd4F`koI|NlrdH7(tVt)Us1h+CSK$7>JpY=LQACB-T00_r zejz!$Ls>*j_zx-e4$Y?@f z-RDLhG#%zjMmpv;U0_WWdbSJz)Ofai#H*);kuun-b#HH@6gILmgKceiw%8iJ#SlkPj1mF=3&WU%FQRfhNtX9Rg8{gOb1~BbFI*C^J7<1 zO)AOVsP>GuiK7Ht?UM>te!6}G7X+q|E}d;InfPsU2C272Ah^0e{&BxRc&kh}{-#tG z_(Au1^8{1%6LR_q*do8Xh*_->!;n$kB(TE?!VId(zFZe;RXJ!5ww-Tw2oEbTVLU#m zyba95xw?zlfoDW_0VT^7P#9{JL9g(+KQwZ=k(ul}_0cpJOjoX~=aW7Ye|3GlQ}IH% z;49Rrr!#rBroDpQZtEbaA&AVsqjJi#HB(0^XZSkDt-Da3PvX$X_Ip>uH_MUA z0UarpcVsAm;2v#v#Qk`ggUGifjRKW$!4!I{F2QH;*CseD}B1h`|vJ8iMXaAfVx@1nv#0P0ir zN*%{@HSDor>`z=5OiU9#0ibe}uH@JM&&$?M(6>Sqcw% z%Joc39uATOUG}|6#=ERuw|cMnC*#TT^_Z6u4>8Fo92< zd{D9K4K9et+pH!ievURixpB#=KYau%#GKh#TZWqtYOt1^}?P=6*hidopKvZ z01;1}xfqYPhB;p9y1Y>qPLC(~<$ktJ4_j!cLp}>hwh^uJ5m)5W(AN3zm~P%19}~g4 zC&BrfAb#}mSLl@Ye-s=W{p8oYSiK5qttn)MWEce7G-Gvk+hJ2DTH~h)#1;?ksR z0vFol;aTb&FRR! zHVpCJ2w0cJLaIxwO&~x&ez%>lOsOf!JkWlrL}D3vM6?@KA;!*6363s;>0N$ z;01~}ZSSNU=g5X|S{)+RzMTl+USXRUr*bR7e8azEJ4V&pN?H#kYT+()oZ^+kX^$C7 zbBcZ;CP*yE4MlGjJ2>s&# z76sOV(I1q0{xIpcwRmr9eu{#qx^29MCqC(n+-hB<4!tE~yQu37SAJk_?k+MYTs|TI zxGk&*hU|-5#C5b?_0Bn8M^UzdBFzd z(XG$VJif&Y`4v2??$pzSFm*d^KwlsO6Y3s4RFZcm8kcI&0`i`^Tc+u44Xp{r6Rd?2 zqrwqB0DFiDlb-VpH)5m?Dvv^++oUC6s_Hxb_vZuz&#n=Re9)DsWwtsLB?Dkuq9#O{;2uGvwh*wM>P{>&ZFkOwXv_-YNs27?Zdg^_mhXVYud+x_-l=T` z65BZN%EwBYp@5}6X3Ax;n*t4O`kKtTL=oRNBEkcM4{Trwds_qtdcDUagXP5klxV9p z%HfJj_Ys7)JRBU3erI=8=9*5!yH#H$HBtQFw>@o(w`RHl?%vd=IBxhuXioXIW`JiS zkUE%xQ?x{Gcv(gu^n`=Ooao|MHYT5qwL!!Bfs-7I$u88}W_iF*#_IT*$}?2qTd^m2d?`k8(^z<@*Sm6+#8Vwt_3BHZfK8Aoj6CW$ zQ^Cskx39lQGS^C8Bqe@l#fsnxqsPyYVv>hR9sGIzA#&%N(0-@}I)U{PGbut<<3xfb zm+Y#ilF>Ku6-7G1$_Ie$cFR6rN2HP^Log3^<1L!S=!{jQ zgaaPohV>Wr7ERr1WGMtq{~Y?&q~oFE;neDBONB9qZlBU4F66=;y&;xpY%k2NGAa3n zqYSPouj&NQs~qwMUFq- z1pe6sn)rU`&GDaKi@JU^!K2%-{v}Og9+@KGd_gt%q46|hM=y2Chmq7?uaumom))4U z%_la^0*}M=k^HnSDR)hrOQl~bmq#+oJ^`*cG;f$1n+d*@VUa#!p(vQt)?m6X>(~HM zs3v|n=d>Vsq*f}Qo5_@sR=Q7P?1qT_)>gXMSWuUDZC*yh*og(A&(cr_Vb4VB8pq&M zhOhQju9QLutrRDo%)XPf}YPkHF!A*0 zvNx=ERot(iJSd*fqEFXDT6ABy<*KTrR<$5H0OukEeSjOHS%jfepMjEn<0dD>V06&j zI7Sw@TDxW49-|Q++&9}0i(!8mU$G(-%8S6ygK8p*P7GtbfAPdiuRgw4e_AZSNK;JD zq9(#_B{^A38f~~Wm!sG-?%=aF{>-~>b8lz46V$9%aHErg+-wzv*}x4$|5QA#-6g{> zmX<|z2gUV1mcSMkDl3<$TJ)9AFE}0F+OD-b_@fR52NbQ&77XH{pSD%mJ&g>D!U_v6 zaKyTU5&lF5?$pFr9Pu+DRXxJsx%of$PozaZFYR)V87a%lZn`m0-+I38jd?rVi`we& zR%*Pn?B~hVXDZgU0&I#r9s0mxsPY8Yw;9Xt?7GbHyk7tN_yKZv`{jAL*YI-R;mPD( z3&ZNl{4C_efo+_fZH|?FpNffxT*W+p46y?;_ z2HZ!lQhQf0T^nOC8Q1)Xyoy@K_u4oRq2#4BeEt;s+GIE)e7aOVi%HiDGu}pu26ml+ zA1>65=_%!2)r#j}{`8?`N~isYk2#bVyongx(E`7#M|G$^%a!=fydepXHIa;86*|mq zNLHq~=$f_qf`i?ctYR{u&s{}Z&>2I_2CQXpO_V|NB;(6 za?NV(c>u7+8&K&NhU90zZu>bHO4ZL|(1;>9Ud=cE)^7OeskYf-%INTL>Wg+&23r1G z&O81jO(P|FmTNZ)oIhB2`Br;GOsQB39&u3fj5S4T zCEy9-kx|olQoS>mt2*yBUe|#8cby~iVTzV^pV4~@A3S2)XnM>fgjT3i3vC6j*_C6^ zS#k$$c-3JPeARPSgMG{Z&tc(qK6cfXBU~#)KNbM(hQn4ET_N~rfr@qGSm7|S*6+L? zbTebA_~cB#TW8Pw&Po}B2O3!8+4e)&g!l7Z*i%JD;}&%iQ=sON=tEi^b^OLuPs%RSBRP}rRm$a@lo^KL$;DVacI4DZz{$mRX+Hg9rrhCJ z)%OJMX}Hii>g2SDJdf$ygV(d|Gy{Pv@UA(RuVScBGSURg_UsPW(&EvCY~|0lp7@0f zXuyX>tEL#Y=&RXkhgv>(uoo&40$^wnG1gx*k0hq%N^k42TDgI*`vDegbE9 z`yEJ)RTFgfmkY378Z;H}HJ*OGLUmjG0}EVp*L_BKgooR|=)IU0Oqy5}D}vY6l1p$( zEk-3P;_trKiTj9MmZdAkg?6;7ZFoOlMi60<<#~;It#@%ZH-yc(d8A1hE}mexarf0_ zT|clik=io)LU+DuKku|A?0f6AcE(rW)o98)u4j1~_EFAW@up z{IMxP@;n^O6(%8*!_xJT<+=dA9ipC`DVKTnU0ZUM4$XZZW&Q7&TD34$r7dkDi&bFR z?g3%K(aj|^Y|YCA#H`*Xa)rF@o7NhsJAFFjI$bK@$CY{ZiG-?D@+U!<)3CUP5pu?A zf0;(lhrTzH16|O=(NB%h?+=;XbKed_Tl6`g_ zh_Xi;!Kk*-qO`5-uMm^P5Fi2Cc3gSKx&7eWB43eF=~Z7jDiKhb3Ze-;L#K(pQGH21-759wuY|WRkqOf`pGK5wgj* zBIPm71sp_9u|3HQa|pYQow4%6%!V_y*K5fiO5(CsZsxAHkGaN7E7~&z(wH;S`w=Zt z&QbQB2V!|p)EF3ju8v~X*_Lainb}l+BiWMn?`(JaJgQN(mka(rJUGlexjr9Rr9J#* zVRo6M*_jX{oIgSlODJ;=98Q^lYCU|zsYZFq(FvEVKf9j5T2tUk1P9wVRtLDS`eb1k z^;(VxIK2O4HEsGsg$oMyG_0UHuo(&3<4GUtG|cjMp}JAg(H#rJa(Qp#+lTpg^iBGn zaC>EgI?uCBy37|a0PMA^*m7l)vT*vP;)fDmdve0U6nWdjMUCeE>d_CoA?nqKT9(-N zt5m}B`lR+4v%tA}T?{36y)e|h_mzEH*7va*yL21GJ}{-?DN)X1k;bR5I@Q3>~Romv9caMPWtZk?La$Cxj8IjYGk4mNFy7fwo z!Ph@F=()3_rB>Zoo=@SB>$WFD=`~R7bnmob@T=bbbP9Lj%gq|4LH?thIba@IvwG>M z%qiHsN!y~k(cty;3J^pNPa`R=AHIs=UWRuI9PLtdqL(vyz_B(Marsh@6+=79b>`*Jf+pH@E;d#9#c_e=jz8!A$t=+o~{ z*jD^46Qy$9W@fOqjw{#d+G{}%*L##>Yi5D(&*y8UK5Q{MPU#v;oS&>R-z79O*6wc1 z*WYR(^K}@sJfJfp2<=%X@$sFrrUVxS45&!^CMjNh_fD!5Y^|3N^p;2cGris{WW7F)-|1_$ve}QPe9-QyvBD%jSX4eKy&KWsW8$@OV|35+RDuHXysy_S#Rr zcXm$OW>UsJDKfx}_^K9i)f2~iBcZViduFi`1$?kVbWv=F08nbehrG$_zA0b*G&c7; z(O+f4Y5!_YtUC;>#IswCjC&8xph)5n2^%Vdd;(dVd5#W9jBeWb>2DYw$BT(Hfys_F zJgo_u2XOy{<<_BS(oF>+yVB79#72+Q^FsVGVa#)Q#fh-9P&#kvO6@;iT*OqqF{F(F zO^5F>1RJq^eDwQ6ACB6adY^chuz1ap!a}bq)fnW;BS<`XRHKh8j@=(?g(B#FSTEyM zREs-p>1L?I*wC16xnv5hI=<`efQCKy)+G`BSe=qW@DUav$P~SMip*qqmYftj=@9c? zd5qJh0dkAN4|e7NOw+Myjc6J5C<|-9Hzb>r9snvjSR1t0CB0>Nw;7hsEW#l0(B{8r zDJUxgO}q`iVUkV4!eIDgeU--oa?4*{vu7ES8|x~WNM(HV6qDNLz2vN4M=hX(9*CT;!_cj31Ot@y^FHYtwvCktS=5Iu zqkf9#BVkjia@s<1+Pj8}0vYIrZqGtJ?r?tOfwhQF8tm_feyz%Qy~@ib^_>~J<4~i; zrwZe7Jg2bH!tm(RQQ_c^sbh?UPp<&tb60pjG5C`zsQj`MqO0XTq%_U#qG_)~=yrLN zHifJh`6jbpPM*7Pn>=QnZC-GY51~WY-((rHrA}|CKHzgWURVYtwG8l@3%RuEeL2c{ zE4zrObe+DJ(qHg8gEn7Z4@l)9W=E6egehU2ZgeY5);H7|QO@;q|LVY4Wyn`F8}E<9 z)1HyiDd;|>l#)Dlyw+^q$+r_;n{B72wcDojYBe%05@GzU-BBe<(%6;dhaAnY2rY3# znI7}rB$xK;Q#N!Bo3@+MHJ`f5MzU1_xMr4iDQOPRX3Y9XP99l`8DXU1N!L6I_sXC# zw^ncUfy~pn$hnr|D}8h*;SpDJ1DT4VSsOwNr_r7dttbglI&v%Lca&q6z%%Z`*93fZyq zDIqw@?%QoGI|ZDIlsc)~w0RGQsygY(v-zWTN{jKk3)S-Rc=Mj+l{qtB)CV69o~PRl^P8W@0|2gK~&0G81jvZFs_VubB+^ zIbP#_Y*(^xJi&IuvW&~3MT<6O=Nyd_pRMiAk%BUkJkN)i6#w<$Qrb!K6ka7Hz(8G?$5hj{iLzy zTZ3n9Fw>$({Q1&TMPfD7XI6pH7n63|eY32>VmBd@af8(SUg%z&YF8uz8l}ovh4@ZH z{!uZ_UBDGcnjret>F%%y4HsJHEi7HD5B%%!WQSXcyjksKPyY-!Ath8F`uIMx?lEgI z1K$TAw0cjHKnM+bOh#YmG+YLGKh)-@;d~wMpV}|zFsHW`KFOc0#-Q-_Vf<`{rE-Jy z@O%d8+KW+xF9TyD#VAnMc=A_a+JFgfm>w@+sZ?cH`fUv|)OOa>)|2jown9-~b7v7x zTF>gISKN)}p-HiWGb=P`Po#%(N#DOL27LVCT;GDpmjIMh9%$Id3}!gveCqzaH-rqk z(DsPpU;PmwK*u?%Wn9cnW?o)(wUlFrCx|+H#id}En`r+-#$-kBE_G};T)kfOG zX(Tv}dK~SMT6XTmDQKVZH0F_?*-VeDd@o#@_wysRCKX){} zi@Ci>xO~;`;pTJy=#?bloN?jGCn>)tTm*j9kV?p-^zwHTAhk1CKtm~H-~Aa(FJ)dCl7qVF?X=cK@>t4qGbjYQ6FXJ}{AO1TK|U-!8m zY* zRpCM$-vy!!KN=>*MR+(`G0d>J@U;f;h8LC$+7v+o!Kc;6p3Q|Qn~4P`dSDW1OPX}z zYgXkulFZ$<Przg~a9X+U_R8&eO+2t+`*_#Lrr+QU|%z2;6P?OtMDmEPga=LAzMWXvN&6=0z6 z8kQVrC&PO6bi9L>+Ul#3m-s|x>bV8|_htm_)cN0&iN8k^aFFKD#evUwYxHy=S{eor zD?1z8)a=;A+|c~u)Eqa}XP6)8(0%(C?JnMf`)!RH--3VeR+O5{dgMC`Pb+l1$!qq# zemz;Zn^=E(Z@GKgakecudW?yasGI+=PvTD|xQ=Jf;ZyKUzw4n~q(+fr?xC{SJtMMW zwa(%qF<=zDEziq!T|hx`eQd9=MN`!_(PV@k#+0KgL$J!Gj>i#dE$l?RG9mhC;Jvkm z41S!Cl`hfFNNr=xzY4s+n!HJqL2*-r9hUX{qwt@ypyU&E-b;~~eTBSr2Qpb5x zjMB~>@*Z%!K?k2|!k9Or2}RK6UwaMTN9(IF`If)7IU`j_tFk<1*R!70A6gD_gVP%o zu^u^$Jqzk|MW47Sm+H_n7Jp(qxCFeR9~q?jx;(?~_AAom4jpv7Y16J5_vd(PCXd`8 zLUQq@f`ZM8#$PVnM=N$zKSXrzV9GZxi*15k5kvy-l7LFtNupE{5rgtg69U8LpV;qL$KS44D{JgSBi7LBV`%n)Ipsk~CHQI+XPa`P^pO)_y!MtOyl!ED zt;c{;P4_V4+kgG)I)QdI@FLlXFKy6miF}s_%3B-UWwU-=wAS8>mdZ2Ig%nMK!Jrkj z<9mCGs;&w7Y7LJX^cpaiiPCzIH_!1~ESau39)3C<-JxCcK0lifX}b1NgRSlgMA5RM z2cCSvC3x^?1)qd6&!{`caM}KZ=OX$r!_+Q?Cle(sW)of=B?jO5I&S9w>s(F&U^c*ZtDk2HBXS(e7SFa%PsO|@<=_#2u zAx+N)ef zvvjNo@;u`;R6NU$d)^y7`>KzbTp1w~;{~uJ1Io|c|6c$&2FLlIjr&iM$cVL$;e!&H zYAqzcQc=M~?gj%2=G0FYg>Z!nc|Fo)DFdsNpS|Cdt_i$-hVV%trJs2x09EjpKwbWf z8Wl{)7MF4{T?FO_;aF*2f~Qz`*~bQGFur?VWsbBCN1qvRYGPDW5a%0D`CTstCV>{N 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 W`Ezn>MyJKGw`T^EbvJvX9r!;Itgn#( literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/body/behavior/reassemble.ftl b/Resources/Locale/en-US/body/behavior/reassemble.ftl new file mode 100644 index 0000000000..b13ac67ad0 --- /dev/null +++ b/Resources/Locale/en-US/body/behavior/reassemble.ftl @@ -0,0 +1,4 @@ +reassemble-action = Reassemble +reassemble-description = Reassemble the pieces of your body. +reassemble-fail = Parts are missing! +reassemble-success = {CAPITALIZE(THE($user))} was put back together. \ No newline at end of file diff --git a/Resources/Prototypes/Body/Parts/skeleton.yml b/Resources/Prototypes/Body/Parts/skeleton.yml new file mode 100644 index 0000000000..f40ed648c5 --- /dev/null +++ b/Resources/Prototypes/Body/Parts/skeleton.yml @@ -0,0 +1,231 @@ +# TODO BODY: Part damage +- type: entity + id: PartSkeleton + parent: BaseItem + name: "skeleton body part" + abstract: true + components: + - type: Damageable + damageContainer: Biological + +- type: entity + id: TorsoSkeleton + name: "skeleton torso" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "torso_m" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "torso_m" + - type: BodyPart + partType: Torso + size: 14 + compatibility: Biological +# criticalThreshold: 100 +# deadThreshold: 150 + +- type: entity + id: HeadSkeleton + name: "skull" + description: Alas poor Yorick... + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "skull_icon" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "skull_icon" + - type: BodyPart + partType: Head + size: 7 + compatibility: Biological + #Unique stuff the skull has for one a skelly gets "boned" nyeheheh + - type: BodyReassemble + action: + icon: Mobs/Species/Skeleton/parts.rsi/full.png + name: reassemble-action + description: reassemble-description + itemIconStyle: NoItem + event: !type:ReassembleActionEvent + - type: Input + context: "human" + - type: Speech + - type: Vocal + - type: Emoting + - type: Grammar + attributes: + proper: true + - type: Examiner + - type: GhostRadio + - type: DoAfter + - type: Actions + - type: MobState + thresholds: + 0: !type:NormalMobState {} + # criticalThreshold: 50 + # deadThreshold: 120 + + + +- type: entity + id: LeftArmSkeleton + name: "left skeleton arm" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_arm" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_arm" + - type: BodyPart + partType: Arm + size: 5 + compatibility: Biological + symmetry: Left + # criticalThreshold: 40 + # deadThreshold: 80 + +- type: entity + id: RightArmSkeleton + name: "right skeleton arm" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_arm" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_arm" + - type: BodyPart + partType: Arm + size: 5 + compatibility: Biological + symmetry: Right + # criticalThreshold: 40 + # deadThreshold: 80 + +- type: entity + id: LeftHandSkeleton + name: "left skeleton hand" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_hand" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_hand" + - type: BodyPart + partType: Hand + size: 3 + compatibility: Biological + symmetry: Left + # criticalThreshold: 30 + # deadThreshold: 60 + +- type: entity + id: RightHandSkeleton + name: "right skeleton hand" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_hand" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_hand" + - type: BodyPart + partType: Hand + size: 3 + compatibility: Biological + symmetry: Right + # criticalThreshold: 30 + # deadThreshold: 60 + +- type: entity + id: LeftLegSkeleton + name: "left skeleton leg" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_leg" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_leg" + - type: BodyPart + partType: Leg + size: 6 + compatibility: Biological + symmetry: Left + +- type: entity + id: RightLegSkeleton + name: "right skeleton leg" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_leg" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_leg" + - type: BodyPart + partType: Leg + size: 6 + compatibility: Biological + symmetry: Right + # criticalThreshold: 45 + # deadThreshold: 90 + +- type: entity + id: LeftFootSkeleton + name: "left skeleton foot" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_foot" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "l_foot" + - type: BodyPart + partType: Foot + size: 2 + compatibility: Biological + symmetry: Left +# criticalThreshold: 30 +# deadThreshold: 60 + +- type: entity + id: RightFootSkeleton + name: "right skeleton foot" + parent: PartSkeleton + components: + - type: Sprite + netsync: false + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_foot" + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: "r_foot" + - type: BodyPart + partType: Foot + size: 2 + compatibility: Biological + symmetry: Right +# criticalThreshold: 30 +# deadThreshold: 60 diff --git a/Resources/Prototypes/Body/Presets/skeleton.yml b/Resources/Prototypes/Body/Presets/skeleton.yml new file mode 100644 index 0000000000..07d372c2eb --- /dev/null +++ b/Resources/Prototypes/Body/Presets/skeleton.yml @@ -0,0 +1,14 @@ +- type: bodyPreset + name: "skeleton" + id: SkeletonPreset + partIDs: + head: HeadSkeleton + torso: TorsoSkeleton + right arm: RightArmSkeleton + left arm: LeftArmSkeleton + right hand: RightHandSkeleton + left hand: LeftHandSkeleton + right leg: RightLegSkeleton + left leg: LeftLegSkeleton + right foot: RightFootSkeleton + left foot: LeftFootSkeleton diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 537655660c..0e9ea58a4a 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -118,6 +118,20 @@ Heat: 3.0 Poison: 0.0 +# immune to everything except physical and heat damage +- type: damageModifierSet + id: Skeleton + coefficients: + Blunt: 2.5 + Slash: 1.5 + Piercing: 1.2 + Cold: 0.0 + Poison: 0.0 + Radiation: 0.0 + Asphyxiation: 0.0 + Bloodloss: 0.0 + Cellular: 0.0 + # Represents which damage types should be modified # in relation to how they cause bloodloss damage. - type: damageModifierSet diff --git a/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml new file mode 100644 index 0000000000..f6d140151c --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Player/skeleton.yml @@ -0,0 +1,28 @@ +- type: entity + save: false + parent: MobSkeletonPersonBase + id: MobSkeletonPerson + components: + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-generic + interactSuccessSound: /Audio/Effects/hug.ogg + messagePerceivedByOthers: hugging-success-generic-others + - type: Mind + showExamineInfo: true + - type: Input + context: "human" + - type: PlayerMobMover + - type: PlayerInputMover + - type: Vocal + maleScream: /Audio/Voice/Skeleton/skeleton_scream.ogg + femaleScream: /Audio/Voice/Skeleton/skeleton_scream.ogg + - type: Alerts + - type: Actions + - type: Eye + - type: CameraRecoil + - type: Examiner + - type: CanHostGuardian + - type: AiFactionTag + factions: + - NanoTrasen diff --git a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml new file mode 100644 index 0000000000..9896bab23f --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml @@ -0,0 +1,352 @@ +- type: entity + save: false + name: Urist McSkelly + id: MobSkeletonPersonBase + description: A miserable pile of bones. + noSpawn: true + components: + - type: Tag + tags: + - CanPilot + - FootstepSound + - DoorBumpOpener + - type: Reactive + groups: + Flammable: [ Touch ] + Extinguish: [ Touch ] + Acidic: [Touch, Ingestion] + reactions: + - reagents: [Water, SpaceCleaner] + methods: [Touch] + effects: + - !type:WashCreamPieReaction + - type: Flashable + - type: Hands + - type: MovementSpeedModifier + - type: MovedByPressure + - type: Markings + - type: Barotrauma + damage: + types: + Blunt: 0.7 #per second, scales with pressure and other constants. + - type: DamageOnHighSpeedImpact + damage: + types: + Blunt: 5 + soundHit: + path: /Audio/Effects/hit_kick.ogg + # Organs + - type: HealthExaminable + examinableTypes: + - Blunt + - Slash + - Piercing + - Heat + - Shock + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - Electrocution + # Other + - type: Inventory + - type: Clickable + - type: InteractionOutline + - type: Icon + sprite: Mobs/Species/Skeleton/parts.rsi + state: full + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + layers: + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Customization/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_arm + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_leg + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_leg + - shader: StencilClear + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: female_full + visible: false + - map: [ "jumpsuit" ] + shader: StencilDraw + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.LFoot" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_foot + - map: [ "enum.HumanoidVisualLayers.RFoot" ] + color: "#ffffff" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_foot + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - type: Physics + bodyType: KinematicController + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + - shape: + !type:PhysShapeCircle + radius: 0.35 + mass: 70 + restitution: 0.0 + mask: + - MobMask + layer: + - MobLayer + - type: AtmosExposed + - type: Flammable + fireSpread: true + canResistFire: true + damage: + types: + Heat: 1 #per second, scales with number of fire 'stacks' + - type: Temperature + heatDamageThreshold: 360 + coldDamageThreshold: 260 + currentTemperature: 310.15 + specificHeat: 42 + coldDamage: + types: + Cold : 1 #per second, scales with temperature & other constants + heatDamage: + types: + Heat : 1 #per second, scales with temperature & other constants + - type: HumanoidAppearance + - type: Body + template: HumanoidTemplate + preset: SkeletonPreset + gibSound: /Audio/Effects/bone_rattle.ogg + - type: Damageable + damageContainer: Biological + damageModifierSet: Skeleton + - type: ThermalRegulator + metabolismHeat: 800 + radiatedHeat: 100 + implicitHeatRegulation: 500 + sweatHeatRegulation: 2000 + shiveringHeatRegulation: 2000 + normalBodyTemperature: 310.15 + thermalRegulationTemperatureThreshold: 25 + - type: Internals + - type: MobState + thresholds: + 0: !type:NormalMobState {} + 100: !type:DeadMobState {} + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:GibBehavior { } + - type: SlowOnDamage #modified speeds because they're so weak + speedModifierThresholds: + 60: 0.9 + 80: 0.7 + 90: 0.5 + - type: HeatResistance + - 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: DamageVisualizer + thresholds: [20, 40, 100] + targetLayers: + - "enum.HumanoidVisualLayers.Chest" + - "enum.HumanoidVisualLayers.Head" + - "enum.HumanoidVisualLayers.LArm" + - "enum.HumanoidVisualLayers.LLeg" + - "enum.HumanoidVisualLayers.RArm" + - "enum.HumanoidVisualLayers.RLeg" + damageOverlayGroups: + Brute: + sprite: Mobs/Effects/brute_damage.rsi + color: "#8a8a8a" + Burn: + sprite: Mobs/Effects/burn_damage.rsi + - type: CombatMode + - type: Climbing + - type: Cuffable + - type: CharacterInfo + - type: AnimationPlayer + - type: Buckle + - type: UnarmedCombat + hitSound: + collection: Punch + range: 0.8 + arcwidth: 30 + arc: fist + damage: + types: + Blunt: 5 + - type: Pullable + - type: DoAfter + - type: CreamPied + - type: Stripping + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Puller + - type: Speech + - type: Vocal + - type: Emoting + - type: Grammar + attributes: + proper: true + - type: StandingState + +- type: entity + save: false + name: Urist McSkelly + parent: MobHumanDummy + id: MobSkeletonPersonDummy + noSpawn: true + description: A dummy skeleton meant to be used in character setup. + components: + - type: Sprite + netsync: false + drawdepth: Mobs + layers: + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Customization/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_arm + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_leg + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_leg + - shader: StencilClear + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: female_full + visible: false + - map: [ "jumpsuit" ] + shader: StencilDraw + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.LFoot" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: l_foot + - map: [ "enum.HumanoidVisualLayers.RFoot" ] + color: "#b8b8b8" + sprite: Mobs/Species/Skeleton/parts.rsi + state: r_foot + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.FacialHair" ] + state: shaved + sprite: Mobs/Customization/human_facial_hair.rsi + color: '#FFFFFF80' + - map: [ "enum.HumanoidVisualLayers.Hair" ] + state: bald + sprite: Mobs/Customization/human_hair.rsi + color: '#FFFFFF80' + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] diff --git a/Resources/Prototypes/species.yml b/Resources/Prototypes/species.yml index 65c794acf2..832a34bd3a 100644 --- a/Resources/Prototypes/species.yml +++ b/Resources/Prototypes/species.yml @@ -30,6 +30,14 @@ dollPrototype: MobSlimePersonDummy skinColoration: Hues +- type: species + id: Skeleton + name: Skeleton + roundStart: false #unspooky, change it in october + prototype: MobSkeletonPerson + dollPrototype: MobSkeletonPersonDummy + skinColoration: TintedHues + #- type: species # id: Vox # name: Vox @@ -37,4 +45,3 @@ # prototype: MobVox # dollPrototype: MobVoxDummy # skinColoration: Hues - diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/full.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/full.png new file mode 100644 index 0000000000000000000000000000000000000000..e457b7018e04a86fc0ea456cf18b8324dd3436a7 GIT binary patch literal 6363 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_f.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_f.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8bd9978bac14783ed867cf4ae5ebb5595a480a GIT binary patch literal 793 zcmV+!1LpjRP)EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;Zt~5CzbmCQFw2GF&f$Zi#X(cG|AMBMWJOI(Z_NIMMM5g(=sw(w3 zPnjRXHZ(YpG=WoN$E+TjSyS9)J0#Zr{A!vvA6F#&LmSqV5u-0ZPW{;H8a($!* z)dZxJ(6%j%F&Ksc&N+1f+WepH_fYMgA~JdJVXZ|<2{Fb~cVZElilSKVo2I$sOGHFO zL_|bHL_|bHMD$d$^alXvpV42MFCtT2*O#5qZ;#09x;`)e-pij^MDBcbf56&&Kzf!K z9DaL%FY zI&~p?tQ#`sW{s}vR9^yhi;OV_ecvyup)Fvqc>(5JV+@Qjza2|NL_|bHL_|bH^cp?^ X%h?}4r4$I^00000NkvXXu0mjfWPfX$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_m.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/head_m.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8bd9978bac14783ed867cf4ae5ebb5595a480a GIT binary patch literal 793 zcmV+!1LpjRP)EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;Zt~5CzbmCQFw2GF&f$Zi#X(cG|AMBMWJOI(Z_NIMMM5g(=sw(w3 zPnjRXHZ(YpG=WoN$E+TjSyS9)J0#Zr{A!vvA6F#&LmSqV5u-0ZPW{;H8a($!* z)dZxJ(6%j%F&Ksc&N+1f+WepH_fYMgA~JdJVXZ|<2{Fb~cVZElilSKVo2I$sOGHFO zL_|bHL_|bHMD$d$^alXvpV42MFCtT2*O#5qZ;#09x;`)e-pij^MDBcbf56&&Kzf!K z9DaL%FY zI&~p?tQ#`sW{s}vR9^yhi;OV_ecvyup)Fvqc>(5JV+@Qjza2|NL_|bHL_|bH^cp?^ X%h?}4r4$I^00000NkvXXu0mjfWPfX$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_arm.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_arm.png new file mode 100644 index 0000000000000000000000000000000000000000..a0764cc340cba20bff3278d802e554d975cd7027 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|=6Jd|hE&XX zdvl{8lOc~w;K6|2)rGFoI~>~Axz6nHII&~mgPK3nqc?93Q!@rCXOL7m>Q{VuXLU;Z zRFQZ4+!@zzh*V8EUtPXlV%IgRuX~Cj_lN!co#raNVe%%XP1nkHe`N>h0)tm)EKm2Z zSgxkoH|@g;uCKnyJ+o)JX1{&BeY#b@{7#klRSo;^GI(CB{$I)iQh&f~o}5bD@~I2O PPJ+0eu6{1-oD!MEX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;0000000000008*S%tk3?^xlV=4Ko{8 z%`vmldmp8gusQdLkZGFa?pl^b?k-7VUDsPgw)Fh`JkQEG%iWby(!TE@*&z$qwoQ^$ zYmJC|tJZpHJ^%m!000000002so!4GKYwfaLz_EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;I(6a`SL`iq2Sn#>bm zn0YdZVQAzH0?l01s-&RJYxKc6+}GBV*?lPi0002MDLLofTI;Q~o^$SJvq~wwlyW-j zom+I^JkM#{wy?ZfYpS)TVHmwtg5L3Tb&tQU>!tVoOLhnV0QlS;;xbRTQB9$F P00000NkvXXu0mjf*MTNJ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_leg.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/l_leg.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d60ddd30a8daf02707cf392f6b9a83cb320225 GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zxjbDQLn`LH zy=9%(Vj$4)@TSJ{kC_(z-I_H@-|d(toqj3SDIIXh@~W5SqPs_UbTs~lUp(X7?C8cg^gSKa!yX5p%}*Iq?EKCIliYMVfl`>N?q9FHtBrZdJ!GT)fx5E|VRc;?LF z`P0w%v?Uf)^ThZy%se^qeM9BEyPtOQ9N4_@wC2(in{+NkO%6JxxK-}@@(;BPYv2Bo z{IEE4R?4hp?|%6As~s!+;&J(D-TwV+&0v=QKbRbt7<>Khbfvn>$EQ8*Sy$hzxitFR zPW3CX9F9fjCI#*KdStWw1>uq}eg}-x)C`Zkt8IKIT<`?QQ*7}yUsTPIev8v0SpUG$ Z8pchbt>*DEX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;ST5Cu?@ahQgQTrd%n zP%?`uz<&F0GMNRHa8}QHG4j|h47g2Kq000000Pr(P@i@vH3k3x0FQ2!&R;k`!A+w8 O0000EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;JE08#0000EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;MA#`iMk-p1aGFi|yN&uadp+y|(ng zy$=};pLcvO|D^O!-#;_z zeSiCW?&-{{&fUr{?lGp7{SeGBT>T)fVe=V|IZOE;c;98{im17@m3#hYkWrqlelF{r G5}E)Lm4^)g literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/skull_icon.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/skull_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8d86abc7aaabb0a5fbc6ecfca2c89d6d69754c49 GIT binary patch literal 870 zcmV-s1DX7ZP)EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;?9jO2>&<346?w--fUl-$xYL2)VYtx zgS7S!M_5Wp)dzr$1CkV9*Y)y`6SdpLDG=W&ac0ObSrp(d(^{jds%QcS0q*i%YkfM0 zR0XL8g%F1^Ap}VrU~YjCGwoQPDh?1L(6+5@ODT7v?wC8y0Z2x`7jXOjnETF!1b}&- zuK`>!A1oyv1TYm4@~|k1VEYv#N1!MQlx1oAWm(<=5e2BK>L4zJ*zI!&LQ1(y!aUED z0MRP&6Upzp?@VM&->rmso-qtV^s5*I&{`kr9QaSLwr%aFIRwVB1Hd2Y<}Pl4fai8h z({z9})^#0#XH?F-2NE};rfD`e@%#hEKlR3Ow8Ba$-=U}_2Mt7B*TM0=@3AZkvMj^0 zEEZNNb?=qT7jmBfFbspu3C=ML5YB;+Xb8fHbG!!#5yrf+<|ZT8 wdw{S7XM3u(zAO$9{+Lj&)i2-wKlU#B1$*sbEoMUmYXATM07*qoM6N<$f}RMBWdHyG literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_f.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_f.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb022a09621d3aab2adaa1767df7c79724f0956 GIT binary patch literal 1030 zcmV+h1o``kP)EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;UinRdv&zJy^i=dQpHPwtU&{}U^1gok7uzm@S<4D#gX8`b#1vxUnpSZ_gg2tHX zPC$Vit+2{gRW%dcGWu)!Qc7s8lj_e5Ih{_M-S)nt|BTx%X8=_^eBkgIu=PXGXZqo1 ztbSAx1pav+0QUQR>=F+lrGznNvLhL5QAiQ}P~SfSFZW~CBWJ+>>+JT){^sP?XBdWI z7=~dOhG7_nVVJ*$e-YYs-K}8y)^%N)7qeb?Z7?F06P|5DbYGzFdz584 zeHTK^x-?s|Y|2_|@7m_yh3tUy`3&H`PoJ_&yqpH{4)L~8AUi-Qg|=;Bt^H9M;GBa} z3diG-v=-R`ZQDXAb$2{>26)@3M0JOEyB&(6fO8I)%Vqj4Rd*&VbW2;PHbfa5Iw58( zF_@Vy+31XW0^!0b#+DQX+>F{KVRtO%%uuXqx6l zYdxD3%Z1l|WJE8zc!g2VSp;+2z%UHMFwF1e9ntn;)n?`V3IG5A07*qoM6N<$g32M` ArvLx| literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_m.png b/Resources/Textures/Mobs/Species/Skeleton/parts.rsi/torso_m.png new file mode 100644 index 0000000000000000000000000000000000000000..22f860dc9199ac8fff9beb2a22564bcdedf8e241 GIT binary patch literal 1058 zcmV+-1l{|IP)EX>4Tx04R}tkv&MmKpe$i(~2S$hjvhL$WWauh)QvkDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRdDMv7M|nl9zMR_MR}I@xj)B%QZO0d6N%@TZdk+{#Ia3F z=e$oGW@SksJ|~_q=z_$LT$f#b<6LrB;F)0~o1P~Q6N{xTmb;jh4V8F?IHIT;t;)8gDW#&^&bgyXva0Dv(jDiCA` zIKj|>RICNSea8fVTm+R;tEr~7M%%WV7eOf{fb}Uj3hW33wHBFP|#jF!v+Zd6`314kPbYGzBI^=mi zp9>)tU79Tko3h53hqn1=Av@r9y8(FY)2Hkbhr2u< zC~&!4NMn&5P}enzqIkHzcLq4ys6=~GM?EQ7Tc<2WvU-?~E+7P-(Cs{Sk0fU2rq z#&LwT7Fm|f*QJz68kI^ZxNR~3p8E4Zgabn1y$J(Bg