diff --git a/Content.Server/Magic/Events/SmiteSpellEvent.cs b/Content.Server/Magic/Events/SmiteSpellEvent.cs
new file mode 100644
index 0000000000..e6aa36a908
--- /dev/null
+++ b/Content.Server/Magic/Events/SmiteSpellEvent.cs
@@ -0,0 +1,12 @@
+using Content.Shared.Actions;
+
+namespace Content.Server.Magic.Events;
+
+public sealed class SmiteSpellEvent : EntityTargetActionEvent
+{
+ ///
+ /// Should this smite delete all parts/mechanisms gibbed except for the brain?
+ ///
+ [DataField("deleteNonBrainParts")]
+ public bool DeleteNonBrainParts = true;
+}
diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs
index bfb4127bf5..f7974e9593 100644
--- a/Content.Server/Magic/MagicSystem.cs
+++ b/Content.Server/Magic/MagicSystem.cs
@@ -1,4 +1,5 @@
using System.Threading;
+using Content.Server.Body.Components;
using Content.Server.Coordinates.Helpers;
using Content.Server.Decals;
using Content.Server.DoAfter;
@@ -9,6 +10,7 @@ using Content.Server.Spawners.Components;
using Content.Server.Weapon.Ranged.Systems;
using Content.Shared.Actions;
using Content.Shared.Actions.ActionTypes;
+using Content.Shared.Body.Components;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Content.Shared.Interaction.Events;
@@ -49,6 +51,7 @@ public sealed class MagicSystem : EntitySystem
SubscribeLocalEvent(OnInstantSpawn);
SubscribeLocalEvent(OnTeleportSpell);
SubscribeLocalEvent(OnKnockSpell);
+ SubscribeLocalEvent(OnSmiteSpell);
SubscribeLocalEvent(OnWorldSpawn);
SubscribeLocalEvent(OnProjectileSpell);
}
@@ -264,6 +267,30 @@ public sealed class MagicSystem : EntitySystem
args.Handled = true;
}
+ private void OnSmiteSpell(SmiteSpellEvent ev)
+ {
+ if (ev.Handled)
+ return;
+
+ if (!TryComp(ev.Target, out var body))
+ return;
+
+ var ents = body.Gib(true);
+
+ if (!ev.DeleteNonBrainParts)
+ return;
+
+ foreach (var part in ents)
+ {
+ // just leaves a brain and clothes
+ if ((HasComp(part) || HasComp(part))
+ && !HasComp(part))
+ {
+ QueueDel(part);
+ }
+ }
+ }
+
///
/// Spawns entity prototypes from a list within range of click.
///
diff --git a/Content.Shared/Body/Components/SharedBodyComponent.cs b/Content.Shared/Body/Components/SharedBodyComponent.cs
index 47b9272df9..76cf0ca4c2 100644
--- a/Content.Shared/Body/Components/SharedBodyComponent.cs
+++ b/Content.Shared/Body/Components/SharedBodyComponent.cs
@@ -397,7 +397,7 @@ namespace Content.Shared.Body.Components
RemovePart(part);
if (gibParts)
- part.Gib();
+ gibs.UnionWith(part.Gib());
}
return gibs;
diff --git a/Content.Shared/Body/Components/SharedBodyPartComponent.cs b/Content.Shared/Body/Components/SharedBodyPartComponent.cs
index 0c0b9bd8f6..875ffe4179 100644
--- a/Content.Shared/Body/Components/SharedBodyPartComponent.cs
+++ b/Content.Shared/Body/Components/SharedBodyPartComponent.cs
@@ -287,12 +287,17 @@ namespace Content.Shared.Body.Components
///
/// Gibs the body part.
///
- public virtual void Gib()
+ public virtual HashSet Gib()
{
+ var gibs = new HashSet();
+
foreach (var mechanism in _mechanisms)
{
+ gibs.Add(mechanism.Owner);
RemoveMechanism(mechanism);
}
+
+ return gibs;
}
}
diff --git a/Resources/Audio/Magic/disintegrate.ogg b/Resources/Audio/Magic/disintegrate.ogg
new file mode 100644
index 0000000000..568a1b43e4
Binary files /dev/null and b/Resources/Audio/Magic/disintegrate.ogg differ
diff --git a/Resources/Audio/Magic/licenses.txt b/Resources/Audio/Magic/licenses.txt
index 90b77db0c7..c8e93f558b 100644
--- a/Resources/Audio/Magic/licenses.txt
+++ b/Resources/Audio/Magic/licenses.txt
@@ -3,5 +3,6 @@ https://github.com/Citadel-Station-13/Citadel-Station-13/blob/master/sound/magic
https://github.com/Citadel-Station-13/Citadel-Station-13/blob/master/sound/magic/Knock.ogg
fireball.ogg taken from /tg/station at https://github.com/tgstation/tgstation/commit/906fb0682bab6a0975b45036001c54f021f58ae7
+disintegrate.ogg from /tg/station at https://github.com/tgstation/tgstation/commit/6fde7a49fcd56d6edb844cd31a04ce026065de8b
-copyright: CC BY-SA 3.0
\ No newline at end of file
+copyright: CC BY-SA 3.0
diff --git a/Resources/Locale/en-US/magic/spells-actions.ftl b/Resources/Locale/en-US/magic/spells-actions.ftl
index 50faf279c5..8368770507 100644
--- a/Resources/Locale/en-US/magic/spells-actions.ftl
+++ b/Resources/Locale/en-US/magic/spells-actions.ftl
@@ -9,6 +9,10 @@ action-name-spell-knock = Knock
action-description-spell-knock = This spell opens nearby doors.
action-speech-spell-knock = AULIE OXIN FIERA
+action-name-spell-smite = Smite
+action-description-spell-smite = Instantly gibs a target.
+action-speech-spell-smite = EI NATH!
+
action-name-spell-blink = Blink
action-description-spell-blink = Teleport to the clicked location.
diff --git a/Resources/Prototypes/Entities/Objects/Magic/books.yml b/Resources/Prototypes/Entities/Objects/Magic/books.yml
index 0992c03c81..67333112e2 100644
--- a/Resources/Prototypes/Entities/Objects/Magic/books.yml
+++ b/Resources/Prototypes/Entities/Objects/Magic/books.yml
@@ -50,6 +50,20 @@
worldSpells:
Blink: -1
+- type: entity
+ id: SmiteBook
+ name: smite spellbook
+ parent: BaseSpellbook
+ components:
+ - type: Sprite
+ netsync: false
+ sprite: Objects/Magic/spellbooks.rsi
+ layers:
+ - state: spellbook
+ - type: Spellbook
+ entitySpells:
+ Smite: -1
+
- type: entity
id: KnockSpellbook
name: knock spellbook
diff --git a/Resources/Prototypes/Magic/smite_spells.yml b/Resources/Prototypes/Magic/smite_spells.yml
new file mode 100644
index 0000000000..c2e31f301c
--- /dev/null
+++ b/Resources/Prototypes/Magic/smite_spells.yml
@@ -0,0 +1,18 @@
+- type: entityTargetAction
+ id: Smite
+ name: action-name-spell-smite
+ description: action-description-spell-smite
+ useDelay: 60
+ speech: action-speech-spell-smite
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ canTargetSelf: false
+ interactOnMiss: false
+ sound: !type:SoundPathSpecifier
+ path: /Audio/Magic/disintegrate.ogg
+ icon:
+ sprite: Objects/Magic/magicactions.rsi
+ state: gib
+ serverEvent: !type:SmiteSpellEvent