The Newest Furry Race [Skeletons] (#7825)

Co-authored-by: Moony <moonheart08@users.noreply.github.com>
Co-authored-by: Kara <lunarautomaton6@gmail.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
EmoGarbage404
2022-05-12 19:35:55 -04:00
committed by GitHub
parent 3467a83d97
commit 075eb0d982
36 changed files with 1093 additions and 37 deletions

View File

@@ -346,6 +346,7 @@ namespace Content.Client.Entry
"DoorRemote",
"InteractionPopup",
"HealthAnalyzer",
"BodyReassemble",
"Thirst",
"CanEscapeInventory",
"PowerSink",

View File

@@ -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;

View File

@@ -83,11 +83,20 @@ namespace Content.Server.Body.Components
}
}
public override void Gib(bool gibParts = false)
public override HashSet<EntityUid> Gib(bool gibParts = false)
{
base.Gib(gibParts);
var gibs = base.Gib(gibParts);
SoundSystem.Play(Filter.Pvs(Owner), _gibSound.GetSound(), _entMan.GetComponent<TransformComponent>(Owner).Coordinates, AudioHelpers.WithVariation(0.025f));
var xform = _entMan.GetComponent<TransformComponent>(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<TransformComponent>(ent).Coordinates = _entMan.GetComponent<TransformComponent>(Owner).Coordinates;
_entMan.GetComponent<TransformComponent>(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<EntityUid> GibbedParts;
public BeingGibbedEvent(HashSet<EntityUid> gibbedParts)
{
GibbedParts = gibbedParts;
}
}
/// <summary>
/// An event raised on all the parts of an entity when it's gibbed
/// </summary>
public sealed class PartGibbedEvent : EntityEventArgs
{
public EntityUid EntityToGib;
public readonly HashSet<EntityUid> GibbedParts;
public PartGibbedEvent(EntityUid entityToGib, HashSet<EntityUid> gibbedParts)
{
EntityToGib = entityToGib;
GibbedParts = gibbedParts;
}
}
}

View File

@@ -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
{
/// <summary>
/// The dna entry used for reassembling the skeleton
/// updated before the entity is gibbed.
/// </summary>
[ViewVariables]
public ClonerDNAEntry? DNA = null;
/// <summary>
/// The default time it takes to reassemble itself
/// </summary>
[ViewVariables]
[DataField("delay")]
public float DoAfterTime = 5f;
/// <summary>
/// The list of body parts that are needed for reassembly
/// </summary>
[ViewVariables]
public HashSet<EntityUid>? BodyParts = null;
[DataField("action")]
public InstantAction? ReassembleAction = null;
public CancellationTokenSource? CancelToken = null;
}
}

View File

@@ -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;
/// <remarks>
/// 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.
/// </remarks>
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<BodyReassembleComponent, PartGibbedEvent>(OnPartGibbed);
SubscribeLocalEvent<BodyReassembleComponent, ReassembleActionEvent>(StartReassemblyAction);
SubscribeLocalEvent<BodyReassembleComponent, GetVerbsEvent<AlternativeVerb>>(AddReassembleVerbs);
SubscribeLocalEvent<BodyReassembleComponent, ReassembleCompleteEvent>(ReassembleComplete);
SubscribeLocalEvent<BodyReassembleComponent, ReassembleCancelledEvent>(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<MindComponent>(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);
}
/// <summary>
/// Adds the custom verb for reassembling body parts
/// </summary>
private void AddReassembleVerbs(EntityUid uid, BodyReassembleComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;
if (!TryComp<MindComponent>(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<EntityUid>? partList)
{
partList = new HashSet<EntityUid>();
if (component.BodyParts == null)
return false;
// Ensures all of the old body part pieces are there
var xformQuery = GetEntityQuery<TransformComponent>();
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<SpeciesPrototype>(component.DNA.Value.Profile.Species).Prototype;
var mob = EntityManager.SpawnEntity(speciesProto, EntityManager.GetComponent<TransformComponent>(component.Owner).MapPosition);
_humanoidAppearance.UpdateFromProfile(mob, component.DNA.Value.Profile);
MetaData(mob).EntityName = component.DNA.Value.Profile.Name;
if (TryComp<MindComponent>(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));
}
/// <summary>
/// Called before the skeleton entity is gibbed in order to save
/// the dna for reassembly later
/// </summary>
/// <param name="uid"> the entity that the player will transfer to</param>
/// <param name="body"> the entity whose DNA is being saved</param>
private void UpdateDNAEntry(EntityUid uid, EntityUid body)
{
if (!TryComp<BodyReassembleComponent>(uid, out var skelBodyComp) || !TryComp<MindComponent>(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
{
/// <summary>
/// The entity being reassembled
/// </summary>
public readonly EntityUid Uid;
/// <summary>
/// The user performing the reassembly
/// </summary>
public readonly EntityUid User;
public readonly HashSet<EntityUid> PartList;
public ReassembleCompleteEvent(EntityUid uid, EntityUid user, HashSet<EntityUid> partList)
{
Uid = uid;
User = user;
PartList = partList;
}
}
private sealed class ReassembleCancelledEvent : EntityEventArgs {}
}
}
public sealed class ReassembleActionEvent : InstantActionEvent { }

View File

@@ -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;

View File

@@ -394,15 +394,19 @@ namespace Content.Shared.Body.Components
}
}
public virtual void Gib(bool gibParts = false)
public virtual HashSet<EntityUid> Gib(bool gibParts = false)
{
var gibs = new HashSet<EntityUid>();
foreach (var part in SlotParts.Keys)
{
gibs.Add(part.Owner);
RemovePart(part);
if (gibParts)
part.Gib();
}
return gibs;
}
}

View File

@@ -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,
}
}

View File

@@ -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).
}

Binary file not shown.

View File

@@ -1,27 +0,0 @@
adminhelp.ogg taken from https://github.com/tgstation/tgstation/blob/d775e1ac804eb9d0259573f5f29a18d320c97ef3/sound/effects/adminhelp.ogg
(available in master, therefore see master license: "All assets including icons and sound are under a Creative Commons 3.0 BY-SA license unless otherwise indicated.")
"Changed the adminhelpsound to some creative commons sound I pinched. Until somebody can get a better one. I'm sick of MAAAAAAAAOOOOOOW."
Actual source is https://freesound.org/people/martian/sounds/19261/ (CC0)
The sound had been reversed and the volume altered.
hit_kick.ogg is made by Taira Komori
(https://taira-komori.jpn.org/freesounden.html)
fire.ogg taken and edited from https://freesound.org/people/raremess/sounds/222557/
holy.ogg taken from https://freesound.org/people/random_intruder/sounds/392172/ and edited
poster_broken.ogg taken from https://github.com/tgstation/tgstation/blob/2834383245d2129a106acef3afd17b81e1e64777/sound/items/poster_ripped.ogg
poster_being_set.ogg taken from https://github.com/tgstation/tgstation/blob/2834383245d2129a106acef3afd17b81e1e64777/sound/items/poster_ripped.ogg
saw.ogg taken from https://freesound.org/people/domiscz/sounds/461728/ and clipped - CC0-1.0
*It's actually an angle grinder
smoke.ogg taken from https://github.com/tgstation/tgstation/blob/a5d362ce84e4f0c61026236d5ec84d3c81553664/sound/effects/smoke.ogg
voteding.ogg taken from "Bike, Bell Ding, Single, 01-01.wav" by InspectorJ (www.jshaw.co.uk) of Freesound.org at https://freesound.org/people/InspectorJ/sounds/484344/ under CC BY 3.0. The volume has been reduced.
minibombcountdown.ogg taken from Thomas Evdokimoff at https://freesound.org/people/thomas_evdokimoff/sounds/202193/
bite.ogg take from https://github.com/tgstation/tgstation/commit/d4f678a1772007ff8d7eddd21cf7218c8e07bfc0

View File

@@ -1 +1,31 @@
adminhelp.ogg taken from https://github.com/tgstation/tgstation/blob/d775e1ac804eb9d0259573f5f29a18d320c97ef3/sound/effects/adminhelp.ogg
(available in master, therefore see master license: "All assets including icons and sound are under a Creative Commons 3.0 BY-SA license unless otherwise indicated.")
"Changed the adminhelpsound to some creative commons sound I pinched. Until somebody can get a better one. I'm sick of MAAAAAAAAOOOOOOW."
Actual source is https://freesound.org/people/martian/sounds/19261/ (CC0)
The sound had been reversed and the volume altered.
hit_kick.ogg is made by Taira Komori
(https://taira-komori.jpn.org/freesounden.html)
fire.ogg taken and edited from https://freesound.org/people/raremess/sounds/222557/
holy.ogg taken from https://freesound.org/people/random_intruder/sounds/392172/ and edited
hug.ogg taken from /tg/station at https://github.com/tgstation/tgstation/blob/e6624ac8aed150668bb4e61c3a48372cc757bfd4/sound/weapons/thudswoosh.ogg - Under license: CC BY-SA 3.0
poster_broken.ogg taken from https://github.com/tgstation/tgstation/blob/2834383245d2129a106acef3afd17b81e1e64777/sound/items/poster_ripped.ogg
poster_being_set.ogg taken from https://github.com/tgstation/tgstation/blob/2834383245d2129a106acef3afd17b81e1e64777/sound/items/poster_ripped.ogg
saw.ogg taken from https://freesound.org/people/domiscz/sounds/461728/ and clipped - CC0-1.0
*It's actually an angle grinder
smoke.ogg taken from https://github.com/tgstation/tgstation/blob/a5d362ce84e4f0c61026236d5ec84d3c81553664/sound/effects/smoke.ogg
voteding.ogg taken from "Bike, Bell Ding, Single, 01-01.wav" by InspectorJ (www.jshaw.co.uk) of Freesound.org at https://freesound.org/people/InspectorJ/sounds/484344/ under CC BY 3.0. The volume has been reduced.
minibombcountdown.ogg taken from Thomas Evdokimoff at https://freesound.org/people/thomas_evdokimoff/sounds/202193/
bite.ogg take from https://github.com/tgstation/tgstation/commit/d4f678a1772007ff8d7eddd21cf7218c8e07bfc0
bone_rattle.ogg licensed under CC0 1.0 and taken from spookymodem at https://freesound.org/people/spookymodem/sounds/202102/

View File

@@ -0,0 +1 @@
skeleton_scream.ogg licensed under CC0 1.0 taken from AntumDeluge at https://freesound.org/people/AntumDeluge/sounds/188034/

Binary file not shown.

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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" ]

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

View File

@@ -0,0 +1,66 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Created by EmoGarbage",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "full"
},
{
"name": "head_f",
"directions": 4
},
{
"name": "head_m",
"directions": 4
},
{
"name": "l_arm",
"directions": 4
},
{
"name": "l_foot",
"directions": 4
},
{
"name": "l_hand",
"directions": 4
},
{
"name": "l_leg",
"directions": 4
},
{
"name": "r_arm",
"directions": 4
},
{
"name": "r_foot",
"directions": 4
},
{
"name": "r_hand",
"directions": 4
},
{
"name": "r_leg",
"directions": 4
},
{
"name": "skull_icon",
"directions": 1
},
{
"name": "torso_f",
"directions": 4
},
{
"name": "torso_m",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB