MeleeHitSoundSystem (#25005)
* Began work to unscrew melee noises * finished * cleanup * cleanup * Update Content.Server/Weapons/Melee/MeleeWeaponSystem.cs Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> * _Style * Fix merge --------- Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -23,6 +23,7 @@ using Content.Shared.Tag;
|
|||||||
using Content.Shared.Weapons.Melee;
|
using Content.Shared.Weapons.Melee;
|
||||||
using Content.Shared.Weapons.Melee.Events;
|
using Content.Shared.Weapons.Melee.Events;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -33,6 +34,7 @@ namespace Content.Server.Weapons.Melee;
|
|||||||
|
|
||||||
public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||||
[Dependency] private readonly ChatSystem _chat = default!;
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
@@ -158,7 +160,8 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio.PlayPvs(combatMode.DisarmSuccessSound, user, AudioParams.Default.WithVariation(0.025f).WithVolume(5f));
|
_audio.PlayPvs(combatMode.DisarmSuccessSound, user, AudioParams.Default.WithVariation(0.025f).WithVolume(5f));
|
||||||
|
AdminLogger.Add(LogType.DisarmedAction, $"{ToPrettyString(user):user} used disarm on {ToPrettyString(target):target}");
|
||||||
|
|
||||||
var targetEnt = Identity.Entity(target, EntityManager);
|
var targetEnt = Identity.Entity(target, EntityManager);
|
||||||
var userEnt = Identity.Entity(user, EntityManager);
|
var userEnt = Identity.Entity(user, EntityManager);
|
||||||
@@ -175,7 +178,6 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
|||||||
PopupSystem.PopupEntity(msgOther, user, filterOther, true);
|
PopupSystem.PopupEntity(msgOther, user, filterOther, true);
|
||||||
PopupSystem.PopupEntity(msgUser, target, user);
|
PopupSystem.PopupEntity(msgUser, target, user);
|
||||||
|
|
||||||
|
|
||||||
if (eventArgs.IsStunned)
|
if (eventArgs.IsStunned)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
[Dependency] private readonly StaminaSystem _stamina = default!;
|
[Dependency] private readonly StaminaSystem _stamina = default!;
|
||||||
[Dependency] private readonly StunSystem _stun = default!;
|
[Dependency] private readonly StunSystem _stun = default!;
|
||||||
|
|
||||||
public const float DamagePitchVariation = SharedMeleeWeaponSystem.DamagePitchVariation;
|
private const float DamagePitchVariation = 0.05f;
|
||||||
public const float GunClumsyChance = 0.5f;
|
public const float GunClumsyChance = 0.5f;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
|
|||||||
108
Content.Shared/Weapons/Melee/MeleeSoundSystem.cs
Normal file
108
Content.Shared/Weapons/Melee/MeleeSoundSystem.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using Content.Shared.Weapons.Melee.Components;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Audio.Systems;
|
||||||
|
|
||||||
|
namespace Content.Shared.Weapons.Melee;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This handles <see cref="MeleeSoundComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MeleeSoundSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
|
public const float DamagePitchVariation = 0.05f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the SwingSound from a weapon component
|
||||||
|
/// for immediate feedback, misses and such
|
||||||
|
/// (Swinging a weapon goes "whoosh" whether it hits or not)
|
||||||
|
/// </summary>
|
||||||
|
public void PlaySwingSound(EntityUid userUid, EntityUid weaponUid, MeleeWeaponComponent weaponComponent)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(weaponComponent.SwingSound, weaponUid, userUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a "damageType" string as an argument and uses it to
|
||||||
|
/// search one of the various Dictionaries in the MeleeSoundComponent
|
||||||
|
/// for a sound to play, and falls back if that fails
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="damageType"> Serves as a lookup key for a hit sound </param>
|
||||||
|
/// <param name="hitSoundOverride"> A sound can be supplied by the <see cref="MeleeHitEvent"/> itself to override everything else </param>
|
||||||
|
public void PlayHitSound(EntityUid targetUid, EntityUid? userUid, string? damageType, SoundSpecifier? hitSoundOverride, MeleeWeaponComponent weaponComponent)
|
||||||
|
{
|
||||||
|
var hitSound = weaponComponent.HitSound;
|
||||||
|
var noDamageSound = weaponComponent.NoDamageSound;
|
||||||
|
|
||||||
|
var playedSound = false;
|
||||||
|
|
||||||
|
if (Deleted(targetUid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// hitting can obv destroy an entity so we play at coords and not following them
|
||||||
|
var coords = Transform(targetUid).Coordinates;
|
||||||
|
// Play sound based off of highest damage type.
|
||||||
|
if (TryComp<MeleeSoundComponent>(targetUid, out var damageSoundComp))
|
||||||
|
{
|
||||||
|
if (damageType == null && damageSoundComp.NoDamageSound != null)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(damageSoundComp.NoDamageSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (damageType != null && damageSoundComp.SoundTypes?.TryGetValue(damageType, out var damageSoundType) == true)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(damageSoundType, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (damageType != null && damageSoundComp.SoundGroups?.TryGetValue(damageType, out var damageSoundGroup) == true)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(damageSoundGroup, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use weapon sounds if the thing being hit doesn't specify its own sounds.
|
||||||
|
if (!playedSound)
|
||||||
|
{
|
||||||
|
if (hitSoundOverride != null)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(hitSoundOverride, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (hitSound != null)
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(hitSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(noDamageSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to generic sounds.
|
||||||
|
if (!playedSound)
|
||||||
|
{
|
||||||
|
switch (damageType)
|
||||||
|
{
|
||||||
|
// Unfortunately heat returns caustic group so can't just use the damagegroup in that instance.
|
||||||
|
case "Burn":
|
||||||
|
case "Heat":
|
||||||
|
case "Radiation":
|
||||||
|
case "Cold":
|
||||||
|
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Items/welder.ogg"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
break;
|
||||||
|
// No damage, fallback to tappies
|
||||||
|
case null:
|
||||||
|
_audio.PlayPredicted(new SoundCollectionSpecifier("WeakHit"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
break;
|
||||||
|
case "Brute":
|
||||||
|
_audio.PlayPredicted(new SoundCollectionSpecifier("MetalThud"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,8 +21,6 @@ using Content.Shared.Weapons.Melee.Events;
|
|||||||
using Content.Shared.Weapons.Ranged.Components;
|
using Content.Shared.Weapons.Ranged.Components;
|
||||||
using Content.Shared.Weapons.Ranged.Events;
|
using Content.Shared.Weapons.Ranged.Events;
|
||||||
using Content.Shared.Weapons.Ranged.Systems;
|
using Content.Shared.Weapons.Ranged.Systems;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Audio.Systems;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
@@ -36,22 +34,21 @@ namespace Content.Shared.Weapons.Melee;
|
|||||||
|
|
||||||
public abstract class SharedMeleeWeaponSystem : EntitySystem
|
public abstract class SharedMeleeWeaponSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
|
||||||
[Dependency] protected readonly IMapManager MapManager = default!;
|
|
||||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
|
||||||
[Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
|
[Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
|
||||||
[Dependency] protected readonly ActionBlockerSystem Blocker = default!;
|
[Dependency] protected readonly ActionBlockerSystem Blocker = default!;
|
||||||
[Dependency] protected readonly DamageableSystem Damageable = default!;
|
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
|
||||||
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
|
||||||
[Dependency] protected readonly SharedCombatModeSystem CombatMode = default!;
|
[Dependency] protected readonly SharedCombatModeSystem CombatMode = default!;
|
||||||
|
[Dependency] protected readonly DamageableSystem Damageable = default!;
|
||||||
[Dependency] protected readonly SharedInteractionSystem Interaction = default!;
|
[Dependency] protected readonly SharedInteractionSystem Interaction = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] protected readonly IMapManager MapManager = default!;
|
||||||
[Dependency] protected readonly SharedPopupSystem PopupSystem = default!;
|
[Dependency] protected readonly SharedPopupSystem PopupSystem = default!;
|
||||||
|
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||||
[Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
|
[Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
|
||||||
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
|
[Dependency] private readonly MeleeSoundSystem _meleeSound = default!;
|
||||||
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
[Dependency] private readonly StaminaSystem _stamina = default!;
|
[Dependency] private readonly StaminaSystem _stamina = default!;
|
||||||
|
|
||||||
public const float DamagePitchVariation = 0.05f;
|
|
||||||
private const int AttackMask = (int) (CollisionGroup.MobMask | CollisionGroup.Opaque);
|
private const int AttackMask = (int) (CollisionGroup.MobMask | CollisionGroup.Opaque);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -83,7 +80,8 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
SubscribeAllEvent<StopAttackEvent>(OnStopAttack);
|
SubscribeAllEvent<StopAttackEvent>(OnStopAttack);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
SubscribeLocalEvent<MeleeWeaponComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<MeleeWeaponComponent,
|
||||||
|
MapInitEvent> (OnMapInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, MeleeWeaponComponent component, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, MeleeWeaponComponent component, MapInitEvent args)
|
||||||
@@ -465,7 +463,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
var missEvent = new MeleeHitEvent(new List<EntityUid>(), user, meleeUid, damage, null);
|
var missEvent = new MeleeHitEvent(new List<EntityUid>(), user, meleeUid, damage, null);
|
||||||
RaiseLocalEvent(meleeUid, missEvent);
|
RaiseLocalEvent(meleeUid, missEvent);
|
||||||
Audio.PlayPredicted(component.SwingSound, meleeUid, user);
|
_meleeSound.PlaySwingSound(user, meleeUid, component);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +518,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayHitSound(target.Value, user, GetHighestDamageSound(modifiedDamage, _protoManager), hitEvent.HitSoundOverride, component.HitSound, component.NoDamageSound);
|
_meleeSound.PlayHitSound(target.Value, user, GetHighestDamageSound(modifiedDamage, _protoManager), hitEvent.HitSoundOverride, component);
|
||||||
|
|
||||||
if (damageResult?.GetTotal() > FixedPoint2.Zero)
|
if (damageResult?.GetTotal() > FixedPoint2.Zero)
|
||||||
{
|
{
|
||||||
@@ -563,7 +561,9 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
var missEvent = new MeleeHitEvent(new List<EntityUid>(), user, meleeUid, damage, direction);
|
var missEvent = new MeleeHitEvent(new List<EntityUid>(), user, meleeUid, damage, direction);
|
||||||
RaiseLocalEvent(meleeUid, missEvent);
|
RaiseLocalEvent(meleeUid, missEvent);
|
||||||
|
|
||||||
Audio.PlayPredicted(component.SwingSound, meleeUid, user);
|
// immediate audio feedback
|
||||||
|
_meleeSound.PlaySwingSound(user, meleeUid, component);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -658,7 +658,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
if (entities.Count != 0)
|
if (entities.Count != 0)
|
||||||
{
|
{
|
||||||
var target = entities.First();
|
var target = entities.First();
|
||||||
PlayHitSound(target, user, GetHighestDamageSound(appliedDamage, _protoManager), hitEvent.HitSoundOverride, component.HitSound, component.NoDamageSound);
|
_meleeSound.PlayHitSound(target, user, GetHighestDamageSound(appliedDamage, _protoManager), hitEvent.HitSoundOverride, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appliedDamage.GetTotal() > FixedPoint2.Zero)
|
if (appliedDamage.GetTotal() > FixedPoint2.Zero)
|
||||||
@@ -702,77 +702,6 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayHitSound(EntityUid target, EntityUid? user, string? type, SoundSpecifier? hitSoundOverride, SoundSpecifier? hitSound, SoundSpecifier? noDamageSound)
|
|
||||||
{
|
|
||||||
var playedSound = false;
|
|
||||||
|
|
||||||
if (Deleted(target))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// hitting can obv destroy an entity so we play at coords and not following them
|
|
||||||
var coords = Transform(target).Coordinates;
|
|
||||||
// Play sound based off of highest damage type.
|
|
||||||
if (TryComp<MeleeSoundComponent>(target, out var damageSoundComp))
|
|
||||||
{
|
|
||||||
if (type == null && damageSoundComp.NoDamageSound != null)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(damageSoundComp.NoDamageSound, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
else if (type != null && damageSoundComp.SoundTypes?.TryGetValue(type, out var damageSoundType) == true)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(damageSoundType, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
else if (type != null && damageSoundComp.SoundGroups?.TryGetValue(type, out var damageSoundGroup) == true)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(damageSoundGroup, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use weapon sounds if the thing being hit doesn't specify its own sounds.
|
|
||||||
if (!playedSound)
|
|
||||||
{
|
|
||||||
if (hitSoundOverride != null)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(hitSoundOverride, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
else if (hitSound != null)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(hitSound, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
else if (noDamageSound != null)
|
|
||||||
{
|
|
||||||
Audio.PlayPredicted(noDamageSound, coords, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
playedSound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to generic sounds.
|
|
||||||
if (!playedSound)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
// Unfortunately heat returns caustic group so can't just use the damagegroup in that instance.
|
|
||||||
case "Burn":
|
|
||||||
case "Heat":
|
|
||||||
case "Radiation":
|
|
||||||
case "Cold":
|
|
||||||
Audio.PlayPredicted(new SoundPathSpecifier("/Audio/Items/welder.ogg"), target, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
break;
|
|
||||||
// No damage, fallback to tappies
|
|
||||||
case null:
|
|
||||||
Audio.PlayPredicted(new SoundCollectionSpecifier("WeakHit"), target, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
break;
|
|
||||||
case "Brute":
|
|
||||||
Audio.PlayPredicted(new SoundCollectionSpecifier("MetalThud"), target, user, AudioParams.Default.WithVariation(DamagePitchVariation));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? GetHighestDamageSound(DamageSpecifier modifiedDamage, IPrototypeManager protoManager)
|
public static string? GetHighestDamageSound(DamageSpecifier modifiedDamage, IPrototypeManager protoManager)
|
||||||
{
|
{
|
||||||
@@ -809,7 +738,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Play a sound to give instant feedback; same with playing the animations
|
// Play a sound to give instant feedback; same with playing the animations
|
||||||
Audio.PlayPredicted(component.SwingSound, meleeUid, user);
|
_meleeSound.PlaySwingSound(user, meleeUid, component);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user