-
Notifications
You must be signed in to change notification settings - Fork 3
Mod Integration Channels
A channel lets two (or more) players hear each other beyond proximity - team comms, faction radio, or a private one-to-one link - with a chosen audio shape (full-volume radio, muffled, or proximity-shaped).
← Back to Mod Integration
You return the channel a player belongs to this frame. Two players that resolve the same key hear each other. Keys are namespaced by your mod id internally, so they never collide with other mods or the built-in channels.
PerfectCommsApi.RegisterVoiceChannel("com.me.mymod", ctx =>
{
// Everyone on the same team shares one key -> they hear each other.
byte team = MyRoles.TeamOf(ctx.Player);
return team != byte.MaxValue
? new VoiceChannelResult($"team:{team}")
: null; // not on a channel this frame
});Return null when the player is not on any channel.
new VoiceChannelResult(
Key, // string: same key on two players = they hear each other
TwoWay = true, // false = directional (see below)
Shape = VoiceAudioShape.Radio,
Volume = 1f);VoiceAudioShape |
Sound |
|---|---|
Radio (default)
|
Full volume, no falloff - classic team comms. |
Muffle |
Heard, but low-pass filtered. Good for "muffled link" effects. |
Proximity |
Proximity-shaped - still falls off with distance, but the pair are linked. |
Volume (0–1) scales the channel audio.
TwoWay: true (default) - both players hear each other.
TwoWay: false - a one-directional link. The reverse direction is suppressed unless the listener also shares a two-way link. Use this for "this role hears its target, but the target does not hear back".
Faction radio (all members hear each other, full volume):
PerfectCommsApi.RegisterVoiceChannel("com.me.mymod", ctx =>
MyRoles.IsCultist(ctx.Player)
? new VoiceChannelResult("cult")
: null);Private pair (owner ↔ target, keyed by the owner so only that pair matches):
PerfectCommsApi.RegisterVoiceChannel("com.me.mymod", ctx =>
{
byte ownerId = MyRoles.LinkOwnerOf(ctx.Player); // owner for both members of the pair
return ownerId != byte.MaxValue
? new VoiceChannelResult($"link:{ownerId}")
: null;
});Muffled "swallowed" link at reduced volume:
PerfectCommsApi.RegisterVoiceChannel("com.me.mymod", ctx =>
MyRoles.SwallowedBy(ctx.Player) is byte predator
? new VoiceChannelResult($"belly:{predator}", Shape: VoiceAudioShape.Muffle, Volume: 0.7f)
: null);One-way overhear (a spy hears a room's occupants, not vice versa):
PerfectCommsApi.RegisterVoiceChannel("com.me.mymod", ctx =>
MyRoles.SpyChannelFor(ctx.Player) is string room
? new VoiceChannelResult(room, TwoWay: false)
: null);- The channel route is evaluated after mutes - a player muted by a Gate stays muted even if they share a channel.
- Channels apply in both meeting and task phases (mirroring the built-in team radio), before built-in radio resolves.
- Like every primitive, channel resolution is local and fail-closed - a throwing callback yields
null(no channel).
- Listener Origin - relocate where a player hears from.
- Host Options & Tabs - gate a channel behind a host toggle.