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)
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.
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 fromnpc_class
. See Localized Information for more info.npc_class + "_killed"
- called when an NPC ofnpc_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 thepvox_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/linkpickup_weapon
here.
- Use
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.
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.