Static helper that plays localized voice lines and shows subtitles. It looks up a VoiceLine resource, plays its localized sound either positioned at a caller GameObject or in 2D, estimates subtitle duration from word count, and posts the subtitle to UI.SubtitleBus.
using System;
using Sandbox;
namespace BrickJam.VoiceLines;
/// <summary>
/// Plays localized voice lines and surfaces their subtitles. Scene-System port of the legacy
/// <c>VoiceLinePlayer</c> entity, reduced to a static helper (the legacy per-line tracking +
/// ConCmds had no in-game callers). Call <see cref="Play"/> from anywhere.
/// </summary>
public static class VoiceLinePlayer
{
/// <summary>
/// Play a voice line by resource path. If <paramref name="caller"/> is valid the sound is
/// positional, otherwise it plays 2D. The localized subtitle is pushed to the HUD.
/// </summary>
public static void Play( GameObject caller, string path )
{
if ( !ResourceLibrary.TryGet<VoiceLine>( path, out var voiceLine ) || !voiceLine.IsValidVoiceLine )
{
Log.Warning( $"Could not find a valid voice line \"{path}\"" );
return;
}
var sound = voiceLine.LocalizedSound;
if ( caller.IsValid() )
Sound.Play( sound, caller.WorldPosition );
else
Sound.Play( sound );
// No public API for a SoundEvent's length, so size the subtitle to the text (reading speed):
// ~2.5 words/sec, clamped to a sane on-screen window.
var subtitle = voiceLine.LocalizedSubtitle;
var words = subtitle?.Split( ' ', StringSplitOptions.RemoveEmptyEntries ).Length ?? 0;
var duration = Math.Clamp( 1.5f + words * 0.4f, 3f, 10f );
UI.SubtitleBus.Post( caller.IsValid() ? caller.Name : "", subtitle, duration );
}
}