Foreword

To begin this documentation, I'd like to start by saying that PVox is not meant to ever be a "REPLACEMENT" for specific VOX addons, all of them present their own caveats and bonuses which make them unique. That's the ideology of the Garry's Mod Workshop, is that there's many different ways to achieve the same effect, and they all have their bonuses

Credits

  • PVox is heavily inspired by and somewhat similar to TFA-VOX.
  • PVox has support for TFA-VOX as well as in-the-works support for PE (Player Expressions)

Introduction

There hasn't been many player voice addons coming up in the past year or so, and that doesn't go without its reason. TFA-VOX, and even the overwhelmingly outdated Player Expressions mod have still dominated the legacy and modern scene, whether it be for pure fun, yet realistic game play.

PVox provides a new approach to player expression, as it is friendly for both the developers making the addon fun for the consumers, and the consumers alike.

Fun Fact: PVox is inspired by TFA-VOX, and Player Expressions, and has made various attempts to support them in the past. If you want to, you can use multiple TFA-VOX mods that add new voices, with PVox, by installing the PVox TFA-VOX Support Layer mod.

So Why Add Another?

Because PVox takes a differing approach to ensuring that call outs happen securely and promptly, yet not being intrusive from a consumer standpoint. This balance makes PVox very suitable for cases where VOX is desirable. Examples such as:

  • Garry's Mod "Realism" Game-play
  • Garry's Mod Role-play
  • Garry's Mod Videos

All of these use cases are examples of where PVox can shine.

How Do I Use It?

PVox comes with spawn-menu entries that can be found in Options > PVOX, these can include module settings, to PVox developer settings and internal variables, all of which can be modified, or looked at through these entries.

To change your preset, you can go to the PVOX > VOX Controls panel to change your preset. You can NOT change other players presets, only modify your own. Presets are updated in real-time and serialized via networked variables, which are predicted, therefore should remain consistent on client and servers alike, even though PVox has a shared module system. See "The Shared Module System" for more information

If you are a developer looking to learn about PVox's API, you can start with anything past 2, as they provide insight into the PVox system as a whole. Getting Dirty With PVox gives a brief overview of the PVox system for the average consumer.

Getting Dirty With PVox

While PVox may seem a bit intimidating at first, especially coming from a more player-model based system like TFA-VOX, or Player Expressions, it is one of the easiest systems to get up and running, as even reported by people using the addon themselves.

To use PVox, simply load into Garry's Mod, open your spawn menu then go to Options > PVOX > VOX Controls. Once you have entered that tab, you will be presented with a drop-down to change your PVox preset. You can select any preset you want, by reading their super secret and secluded code-names, and simply choosing one.

Options > PVOX provides a multitude of features that PVox allows you to change. You have the world at your fingertips! All tabs have a purpose, if they don't, that's a problem. Try changing to another and see what you can modify.

Since they update in real time, and PVox is on by default, you are able to use it like normal, reload, commit other actions(not crimes. That is out of the scope of this book), kill enemies, etc.

PVox modules have server and client presence, which means that clients can see modules, however, they are read-only and non-important data. They are mainly used to read modules, not write to them, as a server maintains its own copy of the modules, and the client can only use those modules as information.

E.g. If you want to check if a player has the module 'pie' installed locally, you can do a nil check in conjunction with GetPlayerModule(), on the client, it checks if the player has it installed LOCALLY, regardless of if it's a multiplayer game to begin with. However, if it's called on in the server realm, it checks if the SERVER can see that module. Client side functions can be called with the local filesystem in hand, therefore can see "ghost modules", or, modules that are installed client-side, and are in the client's files, yet not on the server. For more information on how this works, see The Shared Module System

"Patching" PVox

PVox comes with a patch system, which can be found in the Options > PVOX > Server Patches tab. These are essentially branches of modification built-in to PVox without requiring a separate module or file to be instantiated.

These are considered "conditional features", yet they're called patches for simplicity sake.

Call-out Menu

To create a bind for the call out menu, use the +pvox_open_callout command.

To do that, you can type in the console bind KEY +pvox_open_callout, where KEY is the key you want to bind to opening call-outs.

The Shared Module System

PVox modules, contrary to popular belief, are shared. Which means that on both the client and server, modules are able to be read from and executed. However, only the server can manage proper modules as well as the actual audio code itself.

Take this client side code as an example:

for k, v in pairs(PVox.Modules) do
	Combo:AddChoice( k )
end

This code is found in playervox_spawnmenu.lua and is responsible for adding the client-side modules to the combo box Combo. Notice how no net code, or any server-client magic is used? To get all of the existing modules a simple access to the global PVox.Modules table has sufficed.

This code works because PVox uses a shared module system, in essence, it creates two copies of the modules as they're being made via the ImplementModule function. The client can see its own modules, yet whenever their modules are being called, they're always called from the server.

To the client-side realm, all the mods exist and can work, yet only the server can do real things like modify modules, as well as execute actual action code. If the client's action tables are affected, this means absolutely nothing to the server, and it'll still load like normal.

The PVox Naming Convention

PVox modules can have any name they desire, whether it be lowercase, uppercase, or even all symbols. This is because all modules are simply keys in a dictionary, you can simply add a new module using ImplementModule, and specify its name.

-- e.g. module
if ! PVox then return end

PVox:ImplementModule('My Module', function() return { ... } end)
There's a couple limits to the naming convention when it comes to creating modules, especially procedural modules. When creating a module, if you use the procedural method (via return true), you will notice you have to adhere to Operating System limits.

You can not use uppercase names and lowercase ones interchangeably, due to Windows' filesystem being case insensitive, while Unix-like Operating Systems have a more strict ruling over the case of files and folders.

Therefore, making a procedural module, and calling it A, then making its action table in the pvox/ directory, as a instead of A, will cause issues when your addon is ran on Unix-like devices. This is not a PVox-specific problem, and should be handled and thought of directly by the caller. See the warnings on file.Find and file.Read for more information.

These restrictions do NOT exist on traditional modules.

What About Normal?

When creating a normal module, as opposed to a procedural one where all the files are listed via actual code, a majority of these restrictions are lifted. You can use multiple of PVox's Generator Functions in order to create these sound tables, or write them out manually.

-- ...

PVox:ImplementModule('My Module', function(_)
    return {
        ['actions'] = {
            ['pickup_weapon'] = ...
        }
    }
end)

The PVox Interface

While being a very consumer-friendly, and documented mod, PVox also contains a very comprehensive set of functionalities and abstractions to ensure that it works the way you'd expect.

This section goes over some of the core systems and principles of PVox.

PVox Generators

PVox has generator functions built-in to ease in the process of creating voice lines and other player expressions.

To access these generator functions, simply call the global PVox object.

GenerateSimilarNames

PVox's GenerateSimilarNames function does what you think it does. Generates similar names of files.

The signature is as follows: (from definitions.lua)


--- Generates a table with similar file names. E.g. if you have multiple audio files that are in the format a1.wav, a2.wav, a3.wav, you can
--- use this function to, instead of writing them all out, create a table that automatically generates the names.
---@param amount number      how many names you want to generates
---@param common_name string the common name between all of the files
---@param ext string         the common extension between all the files
---@param zeroes boolean     should zeroes be appended to the filenames < 10? (e.g. a01.wav instead of a1.wav)
---@param prefix string      an (optional) appended prefix for the numbers. e.g. a_01.wav, '_' is the prefix. To disable it, use "" as the prefix for a name like a01.wav
function PVox:GenerateSimilarNames(amount, common_name, ext, zeroes, prefix) end

Usage

To use the function, simply add it into the sound table you would like to define.

From css_ct.lua:

-- ...
    ["enemy_killed"] = PVox:GenerateSimilarNames(3, "playervox/modules/css/enemy_down", "wav", false, ""),
-- ...

This function works because the playervox/modules/css/ directory, looks like this:

playervox/modules/css/enemy_down1.wav
playervox/modules/css/enemy_down2.wav
playervox/modules/css/enemy_down3.wav

Therefore, the table automatically (and lazily) assumes that these files exist, and create the table with the proper file paths. The extension can also be changed for files that are not .WAV.

PVox Actions

Actions are PVox's way of managing sound tables. PVox uses a simple global table in order to manage separate player's modules, and other forms of player sounds.

Globally, the PVox module table looks something like this.


['My Cool Module 1'] = {
    ['actions'] = {...},
    ['callouts'] = {...},
    ['footsteps'] = { [ 'default' ] = { ... } }
},

['My Cool Module 2'] = {
    ['actions'] = {...},
    ['callouts'] = {...},
    ['footsteps'] = { [ 'default' ] = { ... } }
},

The only required field for modules is the actions table. This contains the key value pairs of tables in which sounds can be ran from. Actions are usually string values with no spaces, in all lowercase (with underscores, therefore snake case), and they simply define all of the possible sound files associated with that specific action.

For example, the action pickup_weapon is called whenever a player picks up a weapon. This means that to add sounds that can be used with this, you'd put them in a table.

function pvox_setup_actions()
    return {
        ['actions'] = {
            ['pickup_weapon'] = {
                'my_sound_dir/pickup1_cool.wav',
                'my_sound_dir/pickup2_cool.wav',
                'my_sound_dir/pickup3_cool.wav',
                'my_sound_dir/pickup4_cool.wav',
            }
        }
    }
end

Types

In PVox implementations, there has always been a consistent standard, linking.

When creating an implementation, instead of linking an action string key to a table value, you can link it to another string to instead use THAT action.

['actions'] = {
    ['pickup_weapon'] = "on_ready",
    ['on_ready'] = {
        'a.wav',
        'b.wav',
        'c.wav',
    }
}

And once run in PVox, those sound files will be called whenever a weapon is picked up, OR whenever on_ready is called.

As of 9/2/2024, the pickup_weapon action may not be working as expected with the (VManip) Manual Pickup addon installed. See PVox Weapon Pickup Sound Bug (Issue No. 16) for more information.

Available Actions

While the actual defined amount of actions is unknown, as any action can be ran via EmitAction, and it is up to the defined action-table to create sounds for that string, there are some actions which are frequently emitted from the default PVox codebase.

Those include:

  • "death" - called whenever a player dies.
  • "take_damage_in_vehicle" - called when a player takes damage in a vehicle.
  • "take_damage" - called when a player takes general damage
  • "damage_" + npc_class - called when a player takes damage from npc_class. See Localized Information for more info.
  • npc_class + "_killed" - called when an NPC of npc_class is killed. See Localized Information for more info.
  • "nice_shot" - (New in V9) called when a friendly NPC gets a kill, and the player sees it.
    • (may require the EA patch to be enabled. See Extended Actions for more information.)
  • "enemy_killed" - when a general enemy/thing is killed.
  • "enemy_spotted" - called when an enemy is spotted, or has been tagged.
    • They are therefore known by the current player, and other players around them.
  • "confirm_kill" - when a kill is confirmed. These are separate voice lines and can be created via the pvox_smart_confirm.
  • "reload" - when a player reloads their current weapon.
  • "no_ammo" - called when a player tries to reload their current weapon, but they have no ammo.
  • "pickup_weapon" - called when a player picks up a weapon
  • "on_ready" - called when a player spawns in. However, as of v9, pickup_weapon has precedence over this action.
    • Use pickup_weapon instead, or copy/link pickup_weapon here.

EBA (Extension-Based Actions)

Here are some extension-based actions, or actions which are called from modules, and aren't officially called by PVox itself.

  • inspect - called when the inspect key is pressed. See [The Inspect Module] for more information.

PVox Call-out API

PVox has a call-out API that is designed to be easy to use and supports a multitude of sounds, similar to PVox Actions.

To add call-outs to your VOX pack, the method is the same.

PVOX, as of v9, does NOT support adding a 'callouts' directory. This is because of insecurity and potential vulnerabilities for server owners. If you would like this as an optional feature, you can open an issue on it here.

Accessing Call-outs (v9 ONLY)

To access one of your pack's defined call outs, you can use the +pvox_open_callout command, and bind that to a key like so:

bind x +pvox_open_callout

PVox Server Patches

Patches are simply conditional branches of code which do things different from the main source tree. In PVox, these are in the actual playervox.lua file, and are simply commands that can alter how PVox works. In the PVOX > Server Patches tab, you can find a list of check-boxes, which, when active, will change PVox.

The idea behind patches is that everybody should be able to use PVox how they want to. If there's functionality they want to add, or have, they can either create their own modules with PVox's very easy to use infrastructure, or have the features added by a maintainer. However, these features should NOT interfere with PVox's current edition.

Some server patches currently are:

Reload Chances

Hey! This isn't documented yet. So instead enjoy this horrible drawing of a cat. ^(. _ .)^

Global RNG Patch

Hey! This isn't documented yet. So instead enjoy this horrible drawing of a cat. ^(. _ .)^

Extended Actions (EA)

Hey! This isn't documented yet. So instead enjoy this horrible drawing of a cat. ^(. _ .)^

PVox Footstep Library

Documentation on this is taken directly from the footstep API documentation, found in doc/MANUAL.md

PVox v9 introduces a new footstep API. This new interface allows you to add sounds for specific materials within the Source Engine.

Supported materials are here:

local PLC_PlayerSoundTable = {
	[0]            = "concrete",
	[MAT_CONCRETE] = "concrete",
	[MAT_TILE] = "concrete",
	[MAT_METAL] = "concrete",
	[MAT_GRASS] = "grass",
	[MAT_SNOW] = "snow",
	[MAT_DEFAULT] = "dirt",
	[MAT_DIRT] = "dirt",
	[MAT_WOOD] = "wood",
	[MAT_GRATE] = "grate",
	[MAT_GLASS] = "glass",
	[MAT_FLESH] = "flesh",
}

To create footsteps, you can do it via the classic method, or the procedural way. To make footsteps, you simply must add a ['footsteps'] field to your pack build files.

Every material that you saw there can be used, if you do not want to specify every single material, you are able to make one key, default, and put your file paths into it.

-- in your implementation function...
-- function() return ...
["footsteps"] = {
    ["default"] = {
        "npc/combine_soldier/gear1.wav",
        "npc/combine_soldier/gear2.wav",
        "npc/combine_soldier/gear3.wav",
        "npc/combine_soldier/gear4.wav",
        "npc/combine_soldier/gear5.wav",
        "npc/combine_soldier/gear6.wav",
    }
}

Custom footsteps can be enabled/disabled from the PVox patches menu.

PVox Footstep Library

Documentation on this is taken directly from the footstep API documentation, found in doc/MANUAL.md

PVox v9 introduces a new footstep API. This new interface allows you to add sounds for specific materials within the Source Engine.

Supported materials are here:

local PLC_PlayerSoundTable = {
	[0]            = "concrete",
	[MAT_CONCRETE] = "concrete",
	[MAT_TILE] = "concrete",
	[MAT_METAL] = "concrete",
	[MAT_GRASS] = "grass",
	[MAT_SNOW] = "snow",
	[MAT_DEFAULT] = "dirt",
	[MAT_DIRT] = "dirt",
	[MAT_WOOD] = "wood",
	[MAT_GRATE] = "grate",
	[MAT_GLASS] = "glass",
	[MAT_FLESH] = "flesh",
}

To create footsteps, you can do it via the classic method, or the procedural way. To make footsteps, you simply must add a ['footsteps'] field to your pack build files.

Every material that you saw there can be used, if you do not want to specify every single material, you are able to make one key, default, and put your file paths into it.

-- in your implementation function...
-- function() return ...
["footsteps"] = {
    ["default"] = {
        "npc/combine_soldier/gear1.wav",
        "npc/combine_soldier/gear2.wav",
        "npc/combine_soldier/gear3.wav",
        "npc/combine_soldier/gear4.wav",
        "npc/combine_soldier/gear5.wav",
        "npc/combine_soldier/gear6.wav",
    }
}

Custom footsteps can be enabled/disabled from the PVox patches menu.