Basic gibbing (#2973)

* Adds gibbing

* Adds adminbused absurd-damage foamblade

* Sane parts

* BaseOrgan -> BaseMechanism

* Do not do random offset on shared, fix killing oneself with click attacks

* BaseMechanism -> BaseHumanOrgan -> *stuff*

* Account for prediction, again

* Add gibbing sound
This commit is contained in:
Vera Aguilera Puerto
2021-01-10 20:12:34 +01:00
committed by GitHub
parent 8def38aed4
commit 12c733654c
18 changed files with 172 additions and 29 deletions

View File

@@ -51,39 +51,42 @@ namespace Content.Client.GameObjects.EntitySystems
var attacker = EntityManager.GetEntity(msg.Attacker);
var lunge = attacker.EnsureComponent<MeleeLungeComponent>();
lunge.SetData(msg.Angle);
var entity = EntityManager.SpawnEntity(weaponArc.Prototype, attacker.Transform.Coordinates);
entity.Transform.LocalRotation = msg.Angle;
var weaponArcAnimation = entity.GetComponent<MeleeWeaponArcAnimationComponent>();
weaponArcAnimation.SetData(weaponArc, msg.Angle, attacker, msg.ArcFollowAttacker);
// Due to ISpriteComponent limitations, weapons that don't use an RSI won't have this effect.
if (EntityManager.TryGetEntity(msg.Source, out var source) && msg.TextureEffect && source.TryGetComponent(out ISpriteComponent sourceSprite)
&& sourceSprite.BaseRSI?.Path != null)
if (!attacker.Deleted)
{
var sys = Get<EffectSystem>();
var curTime = _gameTiming.CurTime;
var effect = new EffectSystemMessage
var lunge = attacker.EnsureComponent<MeleeLungeComponent>();
lunge.SetData(msg.Angle);
var entity = EntityManager.SpawnEntity(weaponArc.Prototype, attacker.Transform.Coordinates);
entity.Transform.LocalRotation = msg.Angle;
var weaponArcAnimation = entity.GetComponent<MeleeWeaponArcAnimationComponent>();
weaponArcAnimation.SetData(weaponArc, msg.Angle, attacker, msg.ArcFollowAttacker);
// Due to ISpriteComponent limitations, weapons that don't use an RSI won't have this effect.
if (EntityManager.TryGetEntity(msg.Source, out var source) && msg.TextureEffect && source.TryGetComponent(out ISpriteComponent sourceSprite)
&& sourceSprite.BaseRSI?.Path != null)
{
EffectSprite = sourceSprite.BaseRSI.Path.ToString(),
RsiState = sourceSprite.LayerGetState(0).Name,
Coordinates = attacker.Transform.Coordinates,
Color = Vector4.Multiply(new Vector4(255, 255, 255, 125), 1.0f),
ColorDelta = Vector4.Multiply(new Vector4(0, 0, 0, -10), 1.0f),
Velocity = msg.Angle.ToVec(),
Acceleration = msg.Angle.ToVec() * 5f,
Born = curTime,
DeathTime = curTime.Add(TimeSpan.FromMilliseconds(300f)),
};
sys.CreateEffect(effect);
var sys = Get<EffectSystem>();
var curTime = _gameTiming.CurTime;
var effect = new EffectSystemMessage
{
EffectSprite = sourceSprite.BaseRSI.Path.ToString(),
RsiState = sourceSprite.LayerGetState(0).Name,
Coordinates = attacker.Transform.Coordinates,
Color = Vector4.Multiply(new Vector4(255, 255, 255, 125), 1.0f),
ColorDelta = Vector4.Multiply(new Vector4(0, 0, 0, -10), 1.0f),
Velocity = msg.Angle.ToVec(),
Acceleration = msg.Angle.ToVec() * 5f,
Born = curTime,
DeathTime = curTime.Add(TimeSpan.FromMilliseconds(300f)),
};
sys.CreateEffect(effect);
}
}
foreach (var uid in msg.Hits)
{
if (!EntityManager.TryGetEntity(uid, out var hitEntity))
if (!EntityManager.TryGetEntity(uid, out var hitEntity) || hitEntity.Deleted)
{
continue;
}

View File

@@ -1,15 +1,20 @@
#nullable enable
using System;
using Content.Server.Commands.Observer;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.Utility;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Players;
@@ -41,6 +46,7 @@ namespace Content.Server.GameObjects.Components.Body
base.OnRemovePart(slot, part);
_partContainer.ForceRemove(part.Owner);
part.Owner.RandomOffset(0.25f);
}
public override void Initialize()
@@ -88,5 +94,29 @@ namespace Content.Server.GameObjects.Components.Body
new Ghost().Execute(shell, (IPlayerSession) session, Array.Empty<string>());
}
}
public override void Gib(bool gibParts = false)
{
base.Gib(gibParts);
EntitySystem.Get<AudioSystem>()
.PlayAtCoords(AudioHelpers.GetRandomFileFromSoundCollection("gib"), Owner.Transform.Coordinates,
AudioHelpers.WithVariation(0.025f));
if (Owner.TryGetComponent(out ContainerManagerComponent? container))
{
foreach (var cont in container.GetAllContainers())
{
foreach (var ent in cont.ContainedEntities)
{
cont.ForceRemove(ent);
ent.Transform.Coordinates = Owner.Transform.Coordinates;
ent.RandomOffset(0.25f);
}
}
}
Owner.Delete();
}
}
}

View File

@@ -11,6 +11,7 @@ using Content.Shared.GameObjects.Components.Body.Surgery;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Server.Console;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
@@ -57,6 +58,7 @@ namespace Content.Server.GameObjects.Components.Body.Part
base.OnRemoveMechanism(mechanism);
_mechanismContainer.Remove(mechanism.Owner);
mechanism.Owner.RandomOffset(0.25f);
}
public override void Initialize()

View File

@@ -0,0 +1,27 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Body;
using JetBrains.Annotations;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
[UsedImplicitly]
public class GibBehavior : IThresholdBehavior
{
private bool _recursive = true;
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _recursive, "recursive", true);
}
public void Trigger(IEntity owner, DestructibleSystem system)
{
if (owner.TryGetComponent(out IBody body))
{
body.Gib(_recursive);
}
}
}
}

View File

@@ -79,7 +79,7 @@ namespace Content.Server.GameObjects.Components.Recycling
// Mobs are a special case!
if (CanGib(entity))
{
entity.Delete(); // TODO: Gib
entity.GetComponent<IBody>().Gib(true);
Bloodstain();
return;
}

View File

@@ -247,5 +247,10 @@ namespace Content.Shared.GameObjects.Components.Body
/// <param name="index">The index to look in.</param>
/// <returns>A pair of the part name and body part occupying it.</returns>
KeyValuePair<string, IBodyPart> PartAt(int index);
/// <summary>
/// Gibs this body.
/// </summary>
void Gib(bool gibParts = false);
}
}

View File

@@ -116,5 +116,10 @@ namespace Content.Shared.GameObjects.Components.Body.Part
/// false otherwise.
/// </returns>
bool DeleteMechanism(IMechanism mechanism);
/// <summary>
/// Gibs the body part.
/// </summary>
void Gib();
}
}

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Body.Mechanism;
using Content.Shared.GameObjects.Components.Body.Surgery;
using Content.Shared.Utility;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
@@ -313,6 +314,14 @@ namespace Content.Shared.GameObjects.Components.Body.Part
protected virtual void OnAddedToBody(IBody body) { }
protected virtual void OnRemovedFromBody(IBody old) { }
public virtual void Gib()
{
foreach (var mechanism in _mechanisms)
{
RemoveMechanism(mechanism);
}
}
}
[Serializable, NetSerializable]

View File

@@ -1,6 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Damage;
@@ -11,7 +12,10 @@ using Content.Shared.GameObjects.Components.Body.Template;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Utility;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Containers;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
@@ -19,6 +23,7 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using Component = Robust.Shared.GameObjects.Component;
namespace Content.Shared.GameObjects.Components.Body
{
@@ -697,6 +702,17 @@ namespace Content.Shared.GameObjects.Components.Body
}
}
}
public virtual void Gib(bool gibParts = false)
{
foreach (var (_, part) in Parts)
{
RemovePart(part);
if (gibParts)
part.Gib();
}
}
}
[Serializable, NetSerializable]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,24 @@
- type: entity
id: BaseMechanism
parent: BaseItem
name: "base mechanism"
abstract: true
components:
- type: Mechanism
- type: entity
id: BaseHumanOrgan
parent: BaseMechanism
name: "base human organ"
abstract: true
components:
- type: Sprite
netsync: false
sprite: Mobs/Species/Human/organs.rsi
- type: entity
id: BrainHuman
parent: BaseHumanOrgan
name: "human brain"
description: "The source of incredible, unending intelligence. Honk."
components:
@@ -16,6 +35,7 @@
- type: entity
id: EyesHuman
parent: BaseHumanOrgan
name: "human eyes"
description: "Ocular organ capable of turning light into a colorful visual."
components:
@@ -30,6 +50,7 @@
- type: entity
id: HeartHuman
parent: BaseHumanOrgan
name: "human heart"
description: "Pumps blood throughout a body. Essential for any entity with blood."
components:
@@ -46,6 +67,7 @@
- type: entity
id: LungsHuman
parent: BaseHumanOrgan
name: "human lungs"
description: "Filters oxygen from an atmosphere, which is then sent into the bloodstream to be used as an electron carrier."
components:
@@ -62,6 +84,7 @@
- type: entity
id: StomachHuman
parent: BaseHumanOrgan
name: "human stomach"
description: "Gross. This is hard to stomach."
components:
@@ -82,6 +105,7 @@
- type: entity
id: LiverHuman
parent: BaseHumanOrgan
name: "human liver"
description: "Filters impurities out of a bloodstream and provides other important functionality to a human."
components:
@@ -96,6 +120,7 @@
- type: entity
id: KidneysHuman
parent: BaseHumanOrgan
name: "human kidneys"
description: "Filters toxins out of a bloodstream."
components:

View File

@@ -1,6 +1,7 @@
# TODO BODY: Part damage
- type: entity
id: PartHuman
parent: BaseItem
name: "human body part"
abstract: true

View File

@@ -161,6 +161,11 @@
0: !type:NormalMobState {}
100: !type:CriticalMobState {}
200: !type:DeadMobState {}
- type: Destructible
thresholds:
400:
behaviors:
- !type:GibBehavior { }
- type: HeatResistance
- type: Appearance
visuals:

View File

@@ -528,7 +528,6 @@
- type: Sprite
sprite: Objects/Fun/toys.rsi
state: foamblade
- type: MeleeWeapon
range: 2.0
arcwidth: 0
@@ -539,6 +538,15 @@
HeldPrefix: foamblade
- type: ItemCooldown
- type: entity
name: foamblade
parent: FoamBlade
id: FoamBladeAdminbus
suffix: adminbused
components:
- type: MeleeWeapon
damage: 1000
# MISC
- type: entity

View File

@@ -0,0 +1,6 @@
- type: soundCollection
id: gib
files:
- /Audio/Effects/gib1.ogg
- /Audio/Effects/gib2.ogg
- /Audio/Effects/gib3.ogg

View File

@@ -103,6 +103,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fluidsynth/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=freepats/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gamemode/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gibs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=godmode/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Grindable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hardcode/@EntryIndexedValue">True</s:Boolean>