Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Newest Furry Race [Skeletons] #7825

Merged
merged 36 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1c46b73
Merge branch 'space-wizards-master'
EmoGarbage404 Apr 25, 2022
8bd4c6e
first pass
EmoGarbage404 Apr 27, 2022
8e5f711
color fix
EmoGarbage404 Apr 27, 2022
404cb6d
Merge branch 'space-wizards:master' into master
EmoGarbage404 Apr 27, 2022
bc28856
Merge branch 'space-wizards:master' into master
EmoGarbage404 Apr 28, 2022
a72eba6
syndie bundle
EmoGarbage404 Apr 28, 2022
45f48a6
Update duffelbag.yml
EmoGarbage404 Apr 29, 2022
eed7ef7
Update noninfectious.yml
EmoGarbage404 Apr 29, 2022
9a53aaa
more work
EmoGarbage404 Apr 30, 2022
51e57f8
skeleton reassembly fix
EmoGarbage404 Apr 30, 2022
0fc9bbb
sfx plus sprite fixes
EmoGarbage404 Apr 30, 2022
aa46ec6
Merge branch 'master' into skeletons
EmoGarbage404 Apr 30, 2022
ede4e40
Update species.yml
EmoGarbage404 May 1, 2022
7f6bd4d
feud 1
EmoGarbage404 May 1, 2022
ef51962
Update species.yml
EmoGarbage404 May 1, 2022
a9b55e1
Update species.yml
EmoGarbage404 May 1, 2022
0e53191
Update Content.Server/Body/Systems/TransferMindOnGibSystem.cs
EmoGarbage404 May 4, 2022
b614f7b
Update Content.Server/Body/Systems/SkeletonBodyManagerSystem.cs
EmoGarbage404 May 4, 2022
26f7824
Update Content.Server/Body/Systems/SkeletonBodyManagerSystem.cs
EmoGarbage404 May 4, 2022
88753bf
Update Content.Server/Body/Systems/SkeletonBodyManagerSystem.cs
EmoGarbage404 May 4, 2022
77ab04d
Merge remote-tracking branch 'origin/zombie' into skeletons
EmoGarbage404 May 4, 2022
464058f
Merge remote-tracking branch 'origin/skeletons' into skeletons
EmoGarbage404 May 4, 2022
ed74485
mirror's fixes pt 1
EmoGarbage404 May 4, 2022
8af9804
mirror fixes pt. 2
EmoGarbage404 May 8, 2022
474aac6
Merge branch 'master' into skeletons
EmoGarbage404 May 8, 2022
bce4114
mirror's fixes pt 3. (the finale) (yeehaw)
EmoGarbage404 May 8, 2022
6bf0cf5
Update species.yml
EmoGarbage404 May 8, 2022
da822a3
Merge branch 'master' into skeletons
EmoGarbage404 May 9, 2022
667f1e0
Skeleton man
metalgearsloth May 12, 2022
f1c6791
a
metalgearsloth May 12, 2022
bfbdb30
Merge remote-tracking branch 'upstream/master' into skeletons
metalgearsloth May 12, 2022
ab9a9de
Too spooped
metalgearsloth May 12, 2022
a665713
Update licenses.txt
EmoGarbage404 May 12, 2022
b659679
Create license.txt
EmoGarbage404 May 12, 2022
5dece18
Update licenses.txt
EmoGarbage404 May 12, 2022
7586cb2
Update license.txt
EmoGarbage404 May 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Content.Client/Entry/IgnoredComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@ public static class IgnoredComponents
"EnergySword",
"DoorRemote",
"InteractionPopup",
"HealthAnalyzer"
"HealthAnalyzer",
"SkeletonBodyManager",
"TransferMindOnGib"
};
}
}
11 changes: 11 additions & 0 deletions Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@ private void OnSkinColorOnValueChanged(Range range)
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
break;
}
case SpeciesSkinColor.TintedHues:
{
var color = Color.FromHsv(new Vector4(range.Value / 100.0f, 0.1f, 1.0f, 1.0f));
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
break;
}
}

IsDirty = true;
Expand Down Expand Up @@ -675,6 +681,11 @@ private void UpdateSkinColor()
_skinColor.Value = color.X * 100;
break;
}
case SpeciesSkinColor.TintedHues:
{
_skinColor.Value = color.X * 100f;
break;
}
}

}
Expand Down
19 changes: 16 additions & 3 deletions Content.Server/Body/Components/BodyComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ protected override void Startup()
}
}

public override void Gib(bool gibParts = false)
public override List<SharedBodyPartComponent> Gib(bool gibParts = false)
{
base.Gib(gibParts);
_entMan.EventBus.RaiseLocalEvent(Owner, new BeforeGibbedEvent(), false);
var gibs = base.Gib(gibParts);

SoundSystem.Play(Filter.Pvs(Owner), _gibSound.GetSound(), _entMan.GetComponent<TransformComponent>(Owner).Coordinates, AudioHelpers.WithVariation(0.025f));

Expand All @@ -102,12 +103,24 @@ public override void Gib(bool gibParts = false)
}
}

_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 List<SharedBodyPartComponent> GibbedParts;

public BeingGibbedEvent(List<SharedBodyPartComponent> gibbedParts)
{
GibbedParts = gibbedParts;
}
}

public sealed class BeforeGibbedEvent : EntityEventArgs
{
}
}
28 changes: 28 additions & 0 deletions Content.Server/Body/Components/SkeletonBodyManagerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Server.Cloning;
using Content.Shared.Body.Components;

namespace Content.Server.Body.Components
{
[RegisterComponent]
public sealed class SkeletonBodyManagerComponent : 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]
public float DoAfterTime = 5f;

/// <summary>
/// The list of body parts that are needed for reassembly
/// </summary>
[ViewVariables]
public List<SharedBodyPartComponent>? BodyParts = null;
}
}
13 changes: 13 additions & 0 deletions Content.Server/Body/Components/TransferMindOnGibComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Content.Server.Body.Components
{
[RegisterComponent]
public sealed class TransferMindOnGibComponent : Component
{
/// <summary>
/// The entity the mind will be transferred to
/// stored in here for use in system
/// </summary>
[ViewVariables]
public EntityUid? TransferTarget = null;
}
}
187 changes: 187 additions & 0 deletions Content.Server/Body/Systems/SkeletonBodyManagerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
using Content.Server.Body.Components;
using Content.Server.Cloning;
using Content.Server.Construction;
using Content.Server.DoAfter;
using Content.Server.Mind.Components;
using Content.Server.Popups;
using Content.Server.Preferences.Managers;
using Content.Shared.CharacterAppearance.Systems;
using Content.Shared.Preferences;
using Content.Shared.Species;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using System.Diagnostics.CodeAnalysis;

/// <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 SkeletonBodyManagerSystem : EntitySystem
{
[Dependency] private readonly IEntityManager _entities = default!;
[Dependency] private readonly IServerPreferencesManager _prefsManager = null!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ConstructionSystem _construction = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<SkeletonBodyManagerComponent, GetVerbsEvent<AlternativeVerb>>(AddReassembleVerbs);
SubscribeLocalEvent<ReassembleDoAfterComplete>(Reassemble);
}

/// <summary>
/// Adds the custom verb for reassembling skeleton parts
/// into a full skeleton
/// </summary>
private void AddReassembleVerbs(EntityUid uid, SkeletonBodyManagerComponent component, GetVerbsEvent<AlternativeVerb> args)
{
// every time i get warned of a null refernce i add another if statement
if (!args.CanAccess || !args.CanInteract)
return;

if (!TryComp<ActorComponent?>(args.User, out var actor))
return;

if (!TryComp<MindComponent>(uid, out var mind) || !mind.HasMind)
return;

var doAfterTime = component.DoAfterTime;
// doubles the time if you reconstruct yourself
if (args.User == uid)
doAfterTime *= 2;

// Custom verb
AlternativeVerb custom = new();
custom.Text = Loc.GetString("skeleton-reassemble-action");
custom.Act = () =>
{
if (!GetNearbyParts(args.User, uid, component, out var partList))
return;

if (partList == null)
return;

var doAfterEventArgs = new DoAfterEventArgs(component.Owner, doAfterTime, default, component.Owner)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
BreakOnStun = true,
NeedHand = false,
BroadcastFinishedEvent = new ReassembleDoAfterComplete(uid, args.User, component, partList),
};

_doAfterSystem.DoAfter(doAfterEventArgs);
};
custom.IconTexture = "/Textures/Mobs/Species/Skeleton/parts.rsi/full.png";
custom.Priority = 1;
args.Verbs.Add(custom);
}

private bool GetNearbyParts(EntityUid user, EntityUid uid, SkeletonBodyManagerComponent component, out List<EntityUid>? partList)
{
partList = new List<EntityUid>();

if (component.BodyParts == null)
return false;

// Ensures all of the old body part pieces are there
var nearby = _construction.EnumerateNearby(user);
bool notFound;
foreach (var part in component.BodyParts)
{
notFound = true;
foreach (var entity in nearby)
{
if (part.Owner == entity || part.Owner == component.Owner)
{
notFound = false;
partList.Add(part.Owner);
}
}
if (notFound)
{
_popupSystem.PopupEntity(Loc.GetString("skeleton-reassemble-fail"), uid, Filter.Entities(uid));
return false;
}
}

return true;
}

private void Reassemble(ReassembleDoAfterComplete args)
{
var uid = args.Uid;
var component = args.Component;

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 = _entities.SpawnEntity(speciesProto, _entities.GetComponent<TransformComponent>(component.Owner).MapPosition);

Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(mob, component.DNA.Value.Profile);
_entities.GetComponent<MetaDataComponent>(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)
{
_entities.DeleteEntity(entity);
}

_popupSystem.PopupEntity(Loc.GetString("skeleton-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"></param> the entity the mind is going to be transfered which also stores the DNA
/// <param name="body"></param> the entity whose DNA is being saved
public void UpdateDNAEntry(EntityUid uid, EntityUid body)
{
if (!TryComp<SkeletonBodyManagerComponent>(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 ReassembleDoAfterComplete : EntityEventArgs
{
public readonly EntityUid Uid; //the entity being reassembled
public readonly EntityUid User; //the user performing the reassembly
public readonly SkeletonBodyManagerComponent Component;
public readonly List<EntityUid> PartList;

public ReassembleDoAfterComplete(EntityUid uid, EntityUid user, SkeletonBodyManagerComponent component, List<EntityUid> partList)
{
Uid = uid;
User = user;
Component = component;
PartList = partList;
}
}
}
}
50 changes: 50 additions & 0 deletions Content.Server/Body/Systems/TransferMindOnGibSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Content.Server.Body.Components;
using Content.Server.Mind.Components;

namespace Content.Server.Body.Systems
{
public sealed class TransferMindOnGibSystem : EntitySystem
{
[Dependency] private readonly SkeletonBodyManagerSystem _skeletonBodyManager = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<TransferMindOnGibComponent, BeforeGibbedEvent>(OnBeforeGibbed);
SubscribeLocalEvent<TransferMindOnGibComponent, BeingGibbedEvent>(OnBeingGibbed);
}

private void OnBeforeGibbed(EntityUid uid, TransferMindOnGibComponent component, BeforeGibbedEvent args)
{
if (TryComp<MindComponent>(uid, out var mindComp) && mindComp.Mind != null)
{
if (TryComp<BodyComponent>(uid, out var bodyComp))
{
foreach (var part in bodyComp.Parts)
{
var entity = part.Key.Owner;
if (HasComp<SkeletonBodyManagerComponent>(entity))
{
component.TransferTarget = entity;
_skeletonBodyManager.UpdateDNAEntry(entity, uid);
mindComp.Mind.TransferTo(entity);
}
}
}
}
}

/// <remarks>
/// This information has to be collected in this system because the BeingGibbedEvent
/// is raised locally on the entity
/// </remarks>
private void OnBeingGibbed(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args)
{
if (TryComp<SkeletonBodyManagerComponent>(component.TransferTarget, out var comp))
{
comp.BodyParts = args.GibbedParts;
}
}
}
}
2 changes: 1 addition & 1 deletion Content.Server/Cloning/CloningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void Reset(RoundRestartCleanupEvent ev)
// 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;

Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Construction/ConstructionSystem.Initial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private void InitializeInitial()
}

// LEGACY CODE. See warning at the top of the file!
private IEnumerable<EntityUid> EnumerateNearby(EntityUid user)
public IEnumerable<EntityUid> EnumerateNearby(EntityUid user)
{
foreach (var item in _handsSystem.EnumerateHeld(user))
{
Expand Down
6 changes: 5 additions & 1 deletion Content.Shared/Body/Components/SharedBodyComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,15 +394,19 @@ public override void HandleComponentState(ComponentState? curState, ComponentSta
}
}

public virtual void Gib(bool gibParts = false)
public virtual List<SharedBodyPartComponent> Gib(bool gibParts = false)
{
var gibs = new List<SharedBodyPartComponent>();
foreach (var part in SlotParts.Keys)
{
gibs.Add(part);
RemovePart(part);

if (gibParts)
part.Gib();
}

return gibs;
}
}

Expand Down
Loading