Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

PA Intercom Mod for Dale & Dawson Stationery Supplies

A MelonLoader mod that adds a manager-only intercom to Dale & Dawson Stationery Supplies. Whoever holds the Manager role can broadcast their voice to the whole office from their desk, bypassing the game's normal proximity voice chat, with a cooldown so it can't be spammed.

Features

  • Manager-only. The intercom option only appears for whoever currently holds the Manager role, and only at the Manager's own desk.
  • Radial menu integration. Used the same way as the desk's computer/phone: sit down, hold the interact key, pick "Use the Intercom". Standing up turns it off automatically.
  • Distance bypass. While broadcasting, the Manager's voice is audible everywhere in the office instead of fading out with distance like normal proximity chat.
  • PA speaker effect. The broadcast voice is band-limited and lightly distorted so it sounds like it's coming out of an intercom speaker, not a normal conversation.
  • Cooldown. Configurable (see below), enforced by the host so it can't be bypassed by a modified client.
  • Localized. UI text follows whichever of the game's 23 languages is currently selected.

Requirements

Installation

  1. Install MelonLoader in the game's install folder if you haven't already.
  2. Download PaMod.dll from the Releases page.
  3. Drop it into the game's Mods folder (create it if it doesn't exist next to the game's .exe).
  4. Launch the game once - a settings section will be added automatically (see Configuration).

Every player who wants to hear the intercom broadcast needs the mod installed, not just the Manager or the host - the voice/distance-bypass logic runs on whoever is listening, not on whoever is speaking.

Usage

  1. Whoever is the current Manager sits down at their desk.
  2. Hold the interact key to open the radial menu, same as for the computer or phone.
  3. Pick Use the Intercom to start broadcasting, Turn Off the Intercom to stop (or just stand up).

Configuration

Settings are stored in the game's shared MelonLoader config file:

<game folder>/UserData/MelonPreferences.cfg

under a [PaMod] section:

[PaMod]Cooldown = 60.0
Enabled = true
SettingRangeDescription
Cooldown0 - 180Seconds before the intercom can be used again after being turned off.
Enabledtrue/falseWhether the intercom feature is available at all.

Only the host's value matters. The host's settings are read once at the start of each round and broadcast to every connected client, so everyone plays with the same rules for that round. Edit the file before starting a game - changes made mid-round won't apply until the next one.

Building from source

Open PaMod.csproj and set GameDir to your own game install path, then build with the .NET SDK (dotnet build -c Release). The compiled PaMod.dll ends up in bin/Release/net6.0/.

Project layout

FileResponsibility
Source/PaModMain.csMod entry point; the toggle/cooldown/broadcast state machine.
Source/MicInteraction.csAdds the radial-menu option to the Manager's desk; finds the manager's and the dedicated signal desk.
Source/PaConfig.csHost-configurable settings (MelonPreferences) and their round-start sync.
Source/VoiceEffect.csThe PA speaker audio filter applied to the broadcast voice.
Source/RoomEffectBypass.csBypasses the game's own wall-muffling volume/filter for the boosted voice.
Source/Jingle.csProcedurally generated open/close chime.
Source/MessageDisplay.csThe on-screen warning text (cooldown, wrong role, etc).
Source/Localization.csUI text in all 23 of the game's languages.

Notable technical constraints (read before changing the networking or voice code)

The game is an IL2CPP build, which rules out a few approaches that would otherwise be the obvious way to do this:

  • No new Mirror network message types. Mirror's NetworkMessage is an interface that a struct must implement; IL2CPP can neither inject new value types at runtime nor have an injected class implement an existing IL2CPP interface. Don't try to add a custom NetworkMessage - it throws at registration time.
  • [ClientRpc] methods never reach non-host clients in this build. Confirmed twice, on two unrelated Rpcs: this mod's own RpcSetInteractionTimeCounter attempt, and (still compiled into the Dissonance package itself, not our code) PositionTracker.RpcSetPlayerID. Both reach the server/host and stop there. Treat any [ClientRpc] as unreliable for anything a non-host client needs to see, and prefer a polled SyncVar instead (see below). [Command] (client -> server) has been reliable throughout testing and is unaffected.
  • The PA toggle and the settings sync both ride on Interactable's existing CmdSetInteractionTimeCounter (client -> server, a [Command]) plus a plain SyncVar, interactionCoolDown, polled by every client every 0.5s - not the matching RpcSetInteractionTimeCounter, which was dropped for the reason above. Both features write their value onto a dedicated signal desk (MicInteraction.FindSignalDesk, chosen deterministically by lowest netId, always excluding the Manager's own desk) rather than the Manager's own desk, since hijacking a desk's own cooldown also blocks its radial menu. Real usage of interactionCoolDown is always a non-negative value below the PA toggle's own range, so two disjoint value ranges smuggle both kinds of messages through it without a new network message type - see the sentinel/range constants in PaModMain.cs/PaConfig.cs. If you add a third kind of message, give it its own non-overlapping range.
  • The Manager's Dissonance voice is matched by position, not by Dissonance's own player id.PositionTracker.PlayerId is only ever set through the broken Rpc mentioned above, so StartVoiceBoost (PaModMain.cs) instead finds the closest BaseVoicePlayback to the Manager's character transform (see VoiceMatchMaxDistance). This works because normal proximity voice chat already depends on the same position data reaching every client correctly.
  • Wall-muffling is a separate system from Dissonance's own distance attenuation. The game's RoomEffectController (not part of Dissonance) independently lowers volume and applies its own AudioLowPassFilter based on wall thickness between rooms, regardless of Dissonance's AllowPositionalPlayback flag. RoomEffectBypass patches its Update() with a postfix that forces full volume and our own desired cutoff back onto the boosted voice's entry every frame, the same "re-assert every frame" approach BroadcastHeartbeat uses for the cooldown SyncVar.
  • AudioClip.SetData throws MissingMethodException in this MelonLoader/Il2CppInterop build (a broken interop binding for ReadOnlySpan<T>.GetPinnableReference(), not something fixable by changing the array type). Use AudioClip.Create's streaming PCMReaderCallback instead - see Jingle.cs.

AI disclosure

This mod was developed with assistance from an AI coding assistant - reverse-engineering the game's decompiled IL2CPP code and helping on the implementation.

License

MIT - do whatever you want with it, just keep the copyright notice.

About

A MelonLoader mod for Dale & Dawson Stationery Supplies that add a PA system for the Manager.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages