Repository: Goob-Station/Goob-Station
Pull request #2726: Holocig has music again
Author: login: rotundfan
Labels: name: size/S
description: Denotes a PR that changes 10-99 lines.
name: S: Untriaged
description: A professional will be with you shortly.
name: Changes: Audio
Created: 2025-05-11T19:09:30Z | Merged: 2025-05-18T16:32:46Z

<!--
SPDX-FileCopyrightText: 2021 Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
SPDX-FileCopyrightText: 2021 Swept <sweptwastaken@protonmail.com>
SPDX-FileCopyrightText: 2021 mirrorcult <lunarautomaton6@gmail.com>
SPDX-FileCopyrightText: 2022 AJCM-git <60196617+AJCM-git@users.noreply.github.com>
SPDX-FileCopyrightText: 2022 Kara <lunarautomaton6@gmail.com>
SPDX-FileCopyrightText: 2023 DrSmugleaf <DrSmugleaf@users.noreply.github.com>
SPDX-FileCopyrightText: 2023 Kevin Zheng <kevinz5000@gmail.com>
SPDX-FileCopyrightText: 2024 Vasilis <vasilis@pikachu.systems>
SPDX-FileCopyrightText: 2024 lzk <124214523+lzk228@users.noreply.github.com>
SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>

SPDX-License-Identifier: AGPL-3.0-or-later
-->

<!-- Guidelines: https://docs.spacestation14.io/en/getting-started/pr-guideline -->
<!-- NOTE: All code submitted to this repository is ALWAYS licensed under the AGPL-3.0-or-later license. 
The REUSE Specification headers or separate .license files indicate a secondary license (e.g., MPL or MIT) solely to facilitate 
integration for projects that do not use the AGPL license. This secondary license does not replace the fact that AGPL-3.0-or-later remains the primary and binding license. 
Uncomment and modify the following line if you wish to change the license from the default of AGPL.-->
<!--- LICENSE: AGPL -->
## About the PR
<!-- What did you change? -->
Brought back holocig music with a Durk-Approved remix.
## Why / Balance
<!-- Discuss how this would affect game balance or explain why it was changed. Link any relevant discussions or issues. -->
Silent holocig too strong, also not funny enough.
## Technical details
<!-- Summary of code changes for easier review. -->
fuck if i know man all i know is it works
## Media
<!-- Attach media if the PR makes ingame changes (clothing, items, features, etc).
Small fixes/refactors are exempt. Media may be used in SS14 progress reports with credit. -->

https://github.com/user-attachments/assets/a031cf86-bb73-414f-8057-08b35c31176a



## Requirements
<!-- Confirm the following by placing an X in the brackets [X]: -->
- [X] I have read and am following the [Pull Request and Changelog Guidelines](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
- [X] I have added media to this PR or it does not require an ingame showcase.
<!-- You should understand that not following the above may get your PR closed at maintainer’s discretion -->

## Breaking changes
<!-- List any breaking changes, including namespaces, public class/method/field changes, prototype renames; and provide instructions for fixing them.
This will be posted in #codebase-changes. -->
**Changelog**
<!-- Add a Changelog entry to make players aware of new features or changes that could affect gameplay.
Make sure to read the guidelines and take this Changelog template out of the comment block in order for it to show up.
Changelog must have a :cl: symbol, so the bot recognizes the changes and adds them to the game's changelog. -->
:cl:
- tweak: Long awaited return of holocig music, now without copyright issues.



Diff:
diff --git a/Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs b/Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs
index a7f1d320d60c..763837995224 100644
--- a/Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs
+++ b/Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs
@@ -1,5 +1,7 @@
 // SPDX-FileCopyrightText: 2025 August Eymann <august.eymann@gmail.com>
+// SPDX-FileCopyrightText: 2025 Bandit <queenjess521@gmail.com>
 // SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
+// SPDX-FileCopyrightText: 2025 Ted Lukin <66275205+pheenty@users.noreply.github.com>
 // SPDX-FileCopyrightText: 2025 gus <august.eymann@gmail.com>
 // SPDX-FileCopyrightText: 2025 pheenty <fedorlukin2006@gmail.com>
 //
@@ -19,7 +21,7 @@ public sealed partial class TheManWhoSoldTheWorldComponent : Component
     public EntityUid? HoloCigarEntity = null;
 
     [ViewVariables]
-    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/whouuuHOOAAAAAAAAAAAAH.ogg");
+    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
 
     [DataField]
     public bool AddedNoWieldNeeded;
diff --git a/Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs b/Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs
index 9f487d2dc1f2..42bfe88f05f3 100644
--- a/Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs
+++ b/Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs
@@ -1,5 +1,7 @@
 // SPDX-FileCopyrightText: 2025 August Eymann <august.eymann@gmail.com>
+// SPDX-FileCopyrightText: 2025 Bandit <queenjess521@gmail.com>
 // SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
+// SPDX-FileCopyrightText: 2025 Solstice <solsticeofthewinter@gmail.com>
 // SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
 // SPDX-FileCopyrightText: 2025 Ted Lukin <66275205+pheenty@users.noreply.github.com>
 // SPDX-FileCopyrightText: 2025 gus <august.eymann@gmail.com>
@@ -21,6 +23,14 @@ public sealed partial class HoloCigarComponent : Component
 {
     [ViewVariables]
     public bool Lit;
+
+    [ViewVariables]
+    public SoundSpecifier Music = new SoundPathSpecifier(
+        "/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg",
+        new AudioParams().WithLoop(true).WithVolume(3f));
+
+    [ViewVariables]
+    public EntityUid? MusicEntity;
 }
 
 [Serializable, NetSerializable]
diff --git a/Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs b/Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs
index 51912c359f4c..fd84c1d9072e 100644
--- a/Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs
+++ b/Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs
@@ -1,5 +1,7 @@
 // SPDX-FileCopyrightText: 2025 August Eymann <august.eymann@gmail.com>
+// SPDX-FileCopyrightText: 2025 Bandit <queenjess521@gmail.com>
 // SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
+// SPDX-FileCopyrightText: 2025 Solstice <solsticeofthewinter@gmail.com>
 // SPDX-FileCopyrightText: 2025 SolsticeOfTheWinter <solsticeofthewinter@gmail.com>
 // SPDX-FileCopyrightText: 2025 Ted Lukin <66275205+pheenty@users.noreply.github.com>
 // SPDX-FileCopyrightText: 2025 gus <august.eymann@gmail.com>
@@ -15,11 +17,15 @@
 using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory;
 using Content.Shared.Item;
+using Content.Shared.Mobs;
 using Content.Shared.Smoking;
 using Content.Shared.Verbs;
 using Content.Shared.Weapons.Ranged.Components;
 using Content.Shared.Weapons.Ranged.Systems;
+using Robust.Shared.Audio;
+using Robust.Shared.Audio.Systems;
 using Robust.Shared.GameStates;
+using Robust.Shared.Network;
 using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
@@ -35,6 +41,8 @@ public sealed class HoloCigarSystem : EntitySystem
     [Dependency] private readonly SharedItemSystem _items = default!;
     [Dependency] private readonly SharedGunSystem _gun = default!;
     [Dependency] private readonly IGameTiming _gameTiming = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly INetManager _net = default!;
     [Dependency] private readonly InventorySystem _inventory = default!;
 
     private const string LitPrefix = "lit";
@@ -52,6 +60,7 @@ public override void Initialize()
         SubscribeLocalEvent<TheManWhoSoldTheWorldComponent, PickupAttemptEvent>(OnPickupAttempt);
         SubscribeLocalEvent<TheManWhoSoldTheWorldComponent, MapInitEvent>(OnMapInitEvent);
         SubscribeLocalEvent<TheManWhoSoldTheWorldComponent, ComponentShutdown>(OnComponentShutdown);
+        SubscribeLocalEvent<TheManWhoSoldTheWorldComponent, MobStateChangedEvent>(OnMobStateChangedEvent);
     }
 
     private void OnAddInteractVerb(Entity<HoloCigarComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
@@ -77,11 +86,24 @@ private void OnAddInteractVerb(Entity<HoloCigarComponent> ent, ref GetVerbsEvent
 
     #region Event Methods
 
+    private void OnMobStateChangedEvent(Entity<TheManWhoSoldTheWorldComponent> ent, ref MobStateChangedEvent args)
+    {
+        if (!TryComp<HoloCigarComponent>(ent.Comp.HoloCigarEntity, out var holoCigarComponent))
+            return;
+
+        if (args.NewMobState == MobState.Dead)
+            _audio.Stop(holoCigarComponent.MusicEntity); // no music out of mouth duh
+
+        if (_net.IsServer)
+            _audio.PlayPvs(ent.Comp.DeathAudio, ent, AudioParams.Default.WithVolume(3f));
+    }
+
     private void OnComponentShutdown(Entity<TheManWhoSoldTheWorldComponent> ent, ref ComponentShutdown args)
     {
         if (!TryComp<HoloCigarComponent>(ent.Comp.HoloCigarEntity, out var holoCigarComponent))
             return;
 
+        _audio.Stop(holoCigarComponent.MusicEntity);
         ShutDownEnumerateRemoval(ent);
 
         if (!ent.Comp.AddedNoWieldNeeded)
@@ -163,6 +185,21 @@ private void HandleToggle(Entity<HoloCigarComponent> ent,
         _appearance.SetData(ent, SmokingVisuals.Smoking, state, appearance);
         _clothing.SetEquippedPrefix(ent, prefix, clothing);
         _items.SetHeldPrefix(ent, prefix);
+
+        if (!_net.IsServer) // mary copium right here
+            return;
+
+        if (ent.Comp.Lit == false)
+        {
+            var audio = _audio.PlayPvs(ent.Comp.Music, ent);
+
+            if (audio is null)
+                return;
+            ent.Comp.MusicEntity = audio.Value.Entity;
+            return;
+        }
+
+        _audio.Stop(ent.Comp.MusicEntity);
     }
 
     private void OnComponentHandleState(Entity<HoloCigarComponent> ent, ref ComponentHandleState args)
diff --git a/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg b/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg
new file mode 100644
index 000000000000..03b653eae327
Binary files /dev/null and b/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg differ
diff --git a/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg b/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg
new file mode 100644
index 000000000000..0f73c022c40a
Binary files /dev/null and b/Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg differ


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs (1)</summary><blockquote>

`27-34`: **✧ Grant thy music runes the power of prototypes & minimise their conjuring cost**  

1. Absent `[DataField]`, neither `Music` nor `MusicEntity` may be configured in prototypes. If adjustability be desired, bless them:

```diff
-    [ViewVariables]
-    public SoundSpecifier Music = new SoundPathSpecifier(
+    [ViewVariables, DataField]
+    public SoundSpecifier Music { get; private set; } = new SoundPathSpecifier(
         "/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg",
         new AudioParams().WithLoop(true).WithVolume(3f));
```

2. A new `SoundPathSpecifier` and `AudioParams` is forged for every component instance. Consider forging a single `static readonly` artefact to save cycles of creation:

```csharp
private static readonly SoundSpecifier DefaultMusic =
    new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg",
        new AudioParams().WithLoop(true).WithVolume(3f));

[ViewVariables, DataField]
public SoundSpecifier Music { get; private set; } = DefaultMusic;
```

Such parsimony is gentle on the server’s mana pool.

</blockquote></details>
<details>
<summary>Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs (2)</summary><blockquote>

`106-107`: **✧ Component shutdown should wipe the music sigil as well**  

Mirror the nullification here, else the stale UID lingereth:

```diff
-        _audio.Stop(holoCigarComponent.MusicEntity);
+        _audio.Stop(holoCigarComponent.MusicEntity);
+        holoCigarComponent.MusicEntity = null;
```

---

`189-203`: **✧ Toggle ritual suffers twin-call inconsistency**  

`HandleToggle` is invoked *before* `Lit` flips in `OnAddInteractVerb`, but *after* the flip in `ComponentHandleState`. This asymmetry maketh reasoning perilous and could desync visuals vs. audio on clients during prediction misfires.

Conjure one truth by either:
1. Moving the `ent.Comp.Lit = !ent.Comp.Lit;` line *before* calling `HandleToggle` in the verb, or  
2. Changing `HandleToggle` to compute using `!ent.Comp.Lit` instead of the current value.

Consistency will pacify the prediction imps.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9c831e4e9f35c6bb114090ee8be357b609e02beb and 7eaf2da8da94175ada250add29426a0fe6b95afc.

</details>

<details>
<summary>⛔ Files ignored due to path filters (2)</summary>

* `Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/invisibingle.ogg` is excluded by `!**/*.ogg`
* `Resources/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg` is excluded by `!**/*.ogg`

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs` (2 hunks)
* `Content.Goobstation.Shared/HoloCigar/HoloCigarComponent.cs` (2 hunks)
* `Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs` (6 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: YAML Linter
* GitHub Check: build (ubuntu-latest)
* GitHub Check: build (ubuntu-latest)
* GitHub Check: Test Packaging

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-11T19:15:25Z
user: login: SX-7
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T18:10:21Z

Review comments:
diff_hunk: @@ -19,7 +21,7 @@ public sealed partial class TheManWhoSoldTheWorldComponent : Component
     public EntityUid? HoloCigarEntity = null;
 
     [ViewVariables]
-    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/whouuuHOOAAAAAAAAAAAAH.ogg");
+    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
 
path: Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**✧ Ye Death Cry defineth itself but hideth from the data scrolls**  

The `DeathAudio` field is marked only with `[ViewVariables]`. Without a `[DataField]` incantation, prototype scribes cannot override the sound in YAML and the value will not serialize across the aether. If this limitation be unintended, adorn the field thus:

```diff
-    [ViewVariables]
-    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
+    [ViewVariables, DataField]
+    public SoundSpecifier DeathAudio { get; private set; } = 
+        new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
```

Furthermore, be certain the new `/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg` truly exists within the repo-realm, lest run-time gremlins screech.

---

By the might of the arcane terminal, I shall summon proof of the enchantments in our code!

---

🏁 Script executed:

```shell
#!/bin/bash
# Peering into the component to confirm the presence of DataField runes:
rg -n "TheManWhoSoldTheWorldComponent" -n Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs

# Scanning the realm for any existing DataField adornments:
rg -n "DataField" .

# Seeking the fabled ouchies.ogg within our repository’s depths:
find . -type f -iname "ouchies.ogg"
```

Length of output: 98517

---



</details>

**✧ Necromantic DataField Rune Missing on DeathAudio**

By my arcane audit, the `DeathAudio` field lacks the `[DataField]` enchantment. Without it, prototype scribes cannot override this sound in YAML, and the value will not serialize across the aether.

• File Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs (lines 23–25)  
• Add the `[DataField]` attribute and convert the field to a property with a private setter for proper serialization:

```diff
-    [ViewVariables]
-    public SoundSpecifier DeathAudio = new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
+    [ViewVariables, DataField]
+    public SoundSpecifier DeathAudio { get; private set; } =
+        new SoundPathSpecifier("/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg");
```

Furthermore, I could not unearth the asset `ouchies.ogg` in our repository’s depths. Verify that this file truly exists at `/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg` or commit the missing sound to banish future run-time gremlins.

<details>
<summary>🤖 Prompt for AI Agents (early access)</summary>

```
In
Content.Goobstation.Common/TheManWhoSoldTheWorld/TheManWhoSoldTheWorldComponent.cs
around lines 23 to 25, the DeathAudio field lacks the [DataField] attribute,
preventing YAML overrides and serialization. Add the [DataField] attribute above
DeathAudio and convert it to a property with a private setter to enable proper
serialization. Additionally, verify that the sound file
/Audio/_Goobstation/Items/TheManWhoSoldTheWorld/ouchies.ogg exists in the
repository and commit it if missing to avoid runtime errors.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T19:15:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -77,11 +86,24 @@ private void OnAddInteractVerb(Entity<HoloCigarComponent> ent, ref GetVerbsEvent
 
     #region Event Methods
 
+    private void OnMobStateChangedEvent(Entity<TheManWhoSoldTheWorldComponent> ent, ref MobStateChangedEvent args)
+    {
+        if (!TryComp<HoloCigarComponent>(ent.Comp.HoloCigarEntity, out var holoCigarComponent))
+            return;
+
+        if (args.NewMobState == MobState.Dead)
+            _audio.Stop(holoCigarComponent.MusicEntity); // no music out of mouth duh
+
+        if (_net.IsServer)
+            _audio.PlayPvs(ent.Comp.DeathAudio, ent, AudioParams.Default.WithVolume(3f));
+    }
+
path: Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**✧ Banisht music properly when the bearer meets Death**  

After halting the melody, `MusicEntity` remaineth set, so later calls to `_audio.Stop` smite the same (now dead) entity again. Clear the reference to prevent redundant volleys and possible null-uid shenanigans:

```diff
-        if (args.NewMobState == MobState.Dead)
-            _audio.Stop(holoCigarComponent.MusicEntity); // no music out of mouth duh
+        if (args.NewMobState == MobState.Dead)
+        {
+            _audio.Stop(holoCigarComponent.MusicEntity); // no music out of mouth, duh
+            holoCigarComponent.MusicEntity = null;
+        }
```

Thus the corpse rests in silence, and later shutdowns avoid double-stopping.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    private void OnMobStateChangedEvent(Entity<TheManWhoSoldTheWorldComponent> ent, ref MobStateChangedEvent args)
    {
        if (!TryComp<HoloCigarComponent>(ent.Comp.HoloCigarEntity, out var holoCigarComponent))
            return;

        if (args.NewMobState == MobState.Dead)
        {
            _audio.Stop(holoCigarComponent.MusicEntity); // no music out of mouth, duh
            holoCigarComponent.MusicEntity = null;
        }

        if (_net.IsServer)
            _audio.PlayPvs(ent.Comp.DeathAudio, ent, AudioParams.Default.WithVolume(3f));
    }
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents (early access)</summary>

```
In Content.Goobstation.Shared/HoloCigar/HoloCigarSystem.cs between lines 89 and
100, after calling _audio.Stop on holoCigarComponent.MusicEntity when the mob
state changes to Dead, clear the MusicEntity reference by setting it to null or
an equivalent empty value. This prevents redundant stop calls on the same dead
entity and avoids potential null-uid issues during later shutdowns.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-11T19:15:25Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-11T19:11:24Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

HARK! The code now changeth the path for the DeathAudio sound within the TheManWhoSoldTheWorldComponent, and addeth copyright lines for new contributors. In the HoloCigarComponent, two public fields are born: Music, a looping sound specifier, and MusicEntity, an optional entity identifier. The HoloCigarSystem now summoneth and banisheth music audio entities when the cigar is lit or unlit, and upon the owner's death or component shutdown, the music ceaseth. A handler for MobStateChangedEvent is conjured to ensure these effects, and dependencies on audio and network systems are declared.

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Player
    participant HoloCigarComponent
    participant HoloCigarSystem
    participant AudioSystem

    Player->>HoloCigarSystem: Toggle cigar (lit/unlit)
    alt If lit
        HoloCigarSystem->>AudioSystem: Play looping music
        AudioSystem-->>HoloCigarSystem: Return MusicEntity
        HoloCigarSystem->>HoloCigarComponent: Store MusicEntity
    else If unlit
        HoloCigarSystem->>AudioSystem: Stop MusicEntity
    end

    Player->>HoloCigarSystem: Mob dies
    HoloCigarSystem->>AudioSystem: Stop MusicEntity
    HoloCigarSystem->>AudioSystem: Play DeathAudio (increased volume)
```

## Suggested labels

`Small Bug`

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKNwSPbABsvkCiQBHbGlcSHFcLzpIACIACXwvfAZ4IkhYNGRmbER4BnQibQxoyAB3DPtsAWZ1Gno5MNgPbMo/fFxsDFoAM0x0ZFtIDEcBFoAmAHZRgDZ+LFxGyABxfEEwAGVcanh8LH9ufByCFw0YBeZCxnSMUhQMXApFbAYo+vnUAdR5j394O4faJ7iHb8LqQLI5PJdfB8L5pBJJFIoGjMAA0kC6JGo2Aov1SaD8JGqAA90NxePgpHV5AARbEAaxO7jBbUkW2BIwQnQaqAYVxun3w6FotH8iGQBTY3C8aHkAjQ0owz3QXNgjmhaPKsN4JAk22yXnkOUidzhiWSqTKyCYGBySn89AIgsQ9x2eK5GDa6I6GHkZHw2CIsEZCzQeFg0KF1VwyAIkC88CjUTpHpKkVoN3woNhNF5GFy8sgSk28C8MjwCgwXXgFGYMfSoVhCalhPYbKwJWhdMQwY8H0VXmwSkydHg+MQ4ZKDAyuIaHl5mBumHo1qrNatLClo8VHhK6lgs4J+0O0NkAHJkNxvL5/EEQsrl3ySIlUkRsPAlPHyN3TnPH8/IOwLiDG00gHv47QUFgmamgiqTgrkpR7v6oRMNwsg4oGoRIA40gaOYlgAMIsGwdzIA4TguG4Cw7AaCisOwszcv0dioF0DzMAezR8NwjTsLIaIlOGfR0nQaLRIJ1AoMgSjUPuiD+lyHCIHSV4cNEwY8sRDFoGSmIUDGgojOgkC3s62xQXw+LxphjTOLUBLnBQdIEtK9mxrCthokeOQCLRvxBNWM4qMhxnyR09AkF0GJiH08nJNQUS7vMhaYslEawuGZqIvBDAnAAcoKXTYl8fC0EgDDZDkwIRgw0o4lWU5AjapSUB45K6ko9C/AeTD0aReEGPoxjgFAZD0NBoYEMQZDKPZvUkZwPB8IIIhiJIoH1EwdoqGomjaLoYCGCYUBwKgqC9JNhCkOQVBzVpdxcFQJQVBRsryFtyiqOoWg6ENw2mAYRF3OwGjLIIzpthoRGsDsAD07gALKYAA6uGawJLQ7jI9CXi0PDjRIxgqP4OjuNYzjtDQ/s5B3BoDCIBwBjRMzBgWJAACCACS003Ql9DkY58jQfO1zSFRv4Lk03C0AldYeAABtSqWwOzg7bPL9gKfQVaRDwsm3Ae8uIyjaMY+TFC41TOzsBrtUZMgbEsDEsOq2V+CwwA+mDAgQ01sOc8iiD4yQhPE6TmONNjFt44J/rYNgsQAPKJ+zqdp+nqexBo+BEEQxSxtELtq+7XsrD7mx+wHhJB8bROm2TkcU7D/q8vAuE53nJzs8K6jmfKBporgHaDCQz1rFY1IABoKGhGGwKEn6gSUrVCp16I1Ts9zwAIeDQsg0QAEJLuoxRLjE0BRAAMtgdK/OpkAFfwJVxjnCEb38CTookz0i6QyDL/4MEaAlADXwhzLwNBbrmQMgeJQdsoE7GQNBEgRJ9gUHshGS8vkELsF7mLAwBVyB4WZtEIwEAwBGCBjQWm3tfbmQ0GsdI9pYbxESARFIzgWHwnYQUCgVsaaaHpozEhrNLBcx5rNKIAtnBC1BL/fBTJ5HIGAQ6Ye5BnpYPjJCNuuMYGwnlqw/APDnD8JtowaUYouD4nlujcKaxuCiHgFWSgGsMBoDYPQeWCNsi5A1r8Xu8p4AAC9Ep7mMokfA3BcRogkAkRwJAwAAGZNbhXRCWNqskNRcnxEMHwKhdbywAKJ3HULIAAqu+Vx7ioheJ8QwYp4RZDyxOAfNo+5nG6PQIAxyIl6BJX3PLAA2gANTbiUYZzhRy+WkAAXQ1lCPgvxEAOLWnDJQO9c64h7IgDwKje6IIAkSahDoFi9Wpuwc89gK4eFjL8Wqg5dkEgxP4bcYRBRjhWU4hCOUUnZL+bFBEfMAIlNwPId8uDnEUA1Ika4tobkLBQUgcQ1xIDy0vuoDWAgViRF6F0aURB8qCkRWZFFz4358GtC6XweL8DPVQMwRQXy6CgNEeAyBbY9ELDgXVDlIJDloIwdxSoWjgXhDbogMhHNhRRE0QhDpnjbGdHsY4yFkBvEQg1v0lKPRvALxWFElFYUuTcH1mfWJA42AGztmKVFhjjF8I3NbO4fisDyyoSDWhFd6GMOcHQLhbCOEUH9UYwNpjab03loNKVa9ZV5FydKaZaSnyeIaaUiptAAD8aq6mptBS68x9tbXcNDY6gR+a3Wbw9WXOhOwGFML9XawNwb7VhsEYgSNIjBoA3dTQ6tXra0+uYY23hzbA1rFkM6QkdMGZMxZmzcR11JH80cILPlSjxaXElsgX4LoARKlDG7Hg0pZBygYM5M+zpIkGtSByNAup0ptwdIKWEw7nD2AnciS5vtdlclwaCuMTjRCyFqiQLuI9npKAcZ0MgDAhZYAPdse8I8h6dnfZO2sUlV7Mo5uBgCUgTRXFoJEPgCzUUI0EBsBKBFHy0EKfh3AGtgRGwJibEmZtG7R1bRrS93A5ZgjqTgQ9f6wVZjOIIQs4qkNShlMolKpri6/PGnMBYOyKBSD4HCxCyU7n+AyFEc18Sex0XOSacceBaC0qwDqBiKZ0ClidAQXjB4fkIaJSC2QRmDFLkiNADukQNZsHmIoTDDKyrOKfUemUL9IkzhcwpwSZAeqBsw/GUIF7HNIlKI0LAHRUtoh3qEGicGDyqfU/YcFRnXOitKU81qrzUCXvtAbWEZynWhFI65FoPHr3bIlqLbdwMiC3V2QpylDxfBapa4Gy5qWrkJSQ7CSzM5hMzcA3NmgaIyAOBxCin5PGkFYBkmlDTqpcAWZKPB41x7lFkgeLwUcNBaLAgILnSILL50QNmtAt5sDRA8qakg0EKCBVREwcKnBILxWSu7mvQL4ZaBcHlvdiQ83YnvkgInDA5GBCUZoNRyWtH6MAApc2yGALXMO7GSBR0tqW9gehRVon8KCbHuOSD49FoT7SFAiCIAAJT5utcgAxxbeHjvQ+WntmhPWQ0HQ20XnDX0UHF8iadHaWZdsMAYY6wLxqgkuhI4by57qLSei9Vdm1FCfV2j9A6R0Rp0SjB7d8iAPb+F1KPOgHsIboLt/9KA4xMRdFGDLAAHDLAAnAAFgAIzjAAKzALQKMePAAGFRoxo/TDQKnjEUwBAR8T10PIf0dfzXUM72grv3djK92NO3QA -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Goob-Station/Goob-Station&utm_content=2726):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: pheenty
created_at: 2025-05-11T19:11:25Z
body: what is death sound :skull:
author_association: CONTRIBUTOR
user: login: rotundfan
created_at: 2025-05-11T19:13:40Z
body: > what is death sound 💀

yuou know when uh beter griffin hurts his knee and hes like ssss owwhhh sssssss ohhhadwhhhh yeah its that but bitcrushed (i wanted to make it sound like the traitor radio wew lad guy but i gave up)
author_association: CONTRIBUTOR
user: login: rotundfan
created_at: 2025-05-15T01:30:36Z
body: updated the deathsound and the media sample since yall werent a fan of beter griff
author_association: CONTRIBUTOR