MeleeSoundSystem.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using Content.Shared.Weapons.Melee.Components;
  2. using Content.Shared.Weapons.Melee.Events;
  3. using Robust.Shared.Audio;
  4. using Robust.Shared.Audio.Systems;
  5. namespace Content.Shared.Weapons.Melee;
  6. /// <summary>
  7. /// This handles <see cref="MeleeSoundComponent"/>
  8. /// </summary>
  9. public sealed class MeleeSoundSystem : EntitySystem
  10. {
  11. [Dependency] private readonly SharedAudioSystem _audio = default!;
  12. public const float DamagePitchVariation = 0.05f;
  13. /// <summary>
  14. /// Plays the SwingSound from a weapon component
  15. /// for immediate feedback, misses and such
  16. /// (Swinging a weapon goes "whoosh" whether it hits or not)
  17. /// </summary>
  18. public void PlaySwingSound(EntityUid userUid, EntityUid weaponUid, MeleeWeaponComponent weaponComponent)
  19. {
  20. _audio.PlayPredicted(weaponComponent.SwingSound, weaponUid, userUid);
  21. }
  22. /// <summary>
  23. /// Takes a "damageType" string as an argument and uses it to
  24. /// search one of the various Dictionaries in the MeleeSoundComponent
  25. /// for a sound to play, and falls back if that fails
  26. /// </summary>
  27. /// <param name="damageType"> Serves as a lookup key for a hit sound </param>
  28. /// <param name="hitSoundOverride"> A sound can be supplied by the <see cref="MeleeHitEvent"/> itself to override everything else </param>
  29. public void PlayHitSound(EntityUid targetUid, EntityUid? userUid, string? damageType, SoundSpecifier? hitSoundOverride, MeleeWeaponComponent weaponComponent)
  30. {
  31. var hitSound = weaponComponent.HitSound;
  32. var noDamageSound = weaponComponent.NoDamageSound;
  33. var playedSound = false;
  34. if (Deleted(targetUid))
  35. return;
  36. // hitting can obv destroy an entity so we play at coords and not following them
  37. var coords = Transform(targetUid).Coordinates;
  38. // Play sound based off of highest damage type.
  39. if (TryComp<MeleeSoundComponent>(targetUid, out var damageSoundComp))
  40. {
  41. if (damageType == null && damageSoundComp.NoDamageSound != null)
  42. {
  43. _audio.PlayPredicted(damageSoundComp.NoDamageSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  44. playedSound = true;
  45. }
  46. else if (damageType != null && damageSoundComp.SoundTypes?.TryGetValue(damageType, out var damageSoundType) == true)
  47. {
  48. _audio.PlayPredicted(damageSoundType, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  49. playedSound = true;
  50. }
  51. else if (damageType != null && damageSoundComp.SoundGroups?.TryGetValue(damageType, out var damageSoundGroup) == true)
  52. {
  53. _audio.PlayPredicted(damageSoundGroup, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  54. playedSound = true;
  55. }
  56. }
  57. // Use weapon sounds if the thing being hit doesn't specify its own sounds.
  58. if (!playedSound)
  59. {
  60. if (hitSoundOverride != null)
  61. {
  62. _audio.PlayPredicted(hitSoundOverride, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  63. playedSound = true;
  64. }
  65. else if (hitSound != null)
  66. {
  67. _audio.PlayPredicted(hitSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  68. playedSound = true;
  69. }
  70. else
  71. {
  72. _audio.PlayPredicted(noDamageSound, coords, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  73. playedSound = true;
  74. }
  75. }
  76. // Fallback to generic sounds.
  77. if (!playedSound)
  78. {
  79. switch (damageType)
  80. {
  81. // Unfortunately heat returns caustic group so can't just use the damagegroup in that instance.
  82. case "Burn":
  83. case "Heat":
  84. case "Radiation":
  85. case "Cold":
  86. _audio.PlayPredicted(new SoundPathSpecifier("/Audio/Items/welder.ogg"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  87. break;
  88. // No damage, fallback to tappies
  89. case null:
  90. _audio.PlayPredicted(new SoundCollectionSpecifier("WeakHit"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  91. break;
  92. case "Brute":
  93. _audio.PlayPredicted(new SoundCollectionSpecifier("MetalThud"), targetUid, userUid, AudioParams.Default.WithVariation(DamagePitchVariation));
  94. break;
  95. }
  96. }
  97. }
  98. }