Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/twhl-community/halflife-unified-sdk/llms.txt

Use this file to discover all available pages before exploring further.

The Half-Life Unified SDK replaces the original cfg-based skill system with a streamlined JSON-based approach. Instead of maintaining three cvars per variable and a separate skilldata_t struct field, you simply add a key-value pair to skill.json and read it in code with a single function call. The SDK handles loading, clamping, and networking automatically.
The skill system uses the logger named skill.

Configuration File Syntax

skill.json is a flat JSON object consisting of key-value pairs where each key is a variable name and each value is a number.

Key Naming Rules

Variable names must follow these rules:
  • May contain uppercase and lowercase alphabetical characters and underscores
  • Numbers are allowed but not at the start or end of the name

Setting Values for Skill Levels

You can set a value for all three skill levels at once by using the plain variable name:
"my_variable": 10
To set different values for each skill level individually, append the skill level index (1, 2, or 3) to the variable name:
"my_variable1": 10,
"my_variable2": 8,
"my_variable3": 5
Using both the plain name and the indexed names for the same variable at the same time is not supported and will produce incorrect results. Choose one approach per variable.

Skill Levels

LevelIndex
Easy1
Medium2
Hard3

Example

{
	"plr_crowbar": 10,
	// HEALTH/SUIT CHARGE DISTRIBUTION
	"suitcharger1": 75,
	"suitcharger2": 50,
	"suitcharger3": 35
}
In this example, plr_crowbar is set to 10 for all skill levels, while suitcharger has decreasing values from Easy (75) through Medium (50) to Hard (35). Refer to the skill.json file included with the SDK for the full list of variables used by the built-in game code.

Using Skill Variables in Code

To read a skill variable in C++, call GetSkillFloat with the variable name:
GetSkillFloat("my_variable"sv)
GetSkillFloat is a static method of CBaseEntity and internally calls g_Skill.GetValue. It accepts a std::string_view, which is why the sv string literal suffix is used — this avoids calculating the string length at each call site. No registration or other setup is required to read a skill variable. If the variable has not been defined in skill.json, the call returns 0 by default.

Defining Variables with Constraints

Skill variables can be formally defined in code to attach constraints (minimum value, maximum value, type, and networking). This is done inside ServerLibrary::DefineSkillVariables.
Variables should only be defined on the server side. The client receives all networked variable values automatically when it connects to the server.

Defining a Variable with a Default Value

g_Skill.DefineVariable("my_variable", 60);
This registers my_variable with a default value of 60. If skill.json does not provide a value, 60 is used instead of the fallback of 0.

Adding a Minimum Constraint

g_Skill.DefineVariable("my_variable", 60, {.Minimum = -1});
Values smaller than -1 are clamped to -1.

Adding Multiple Constraints

g_Skill.DefineVariable("chainsaw_melee", 0, {.Minimum = 0, .Maximum = 1, .Networked = true, .Type = SkillVarType::Integer});

Constraint Reference

NamePurpose
MinimumMinimum allowed value; values below this are clamped up
MaximumMaximum allowed value; values above this are clamped down
NetworkedWhen true, the value is sent to clients so that client-side code can access it
TypeType of the value. Defaults to float. Set to SkillVarType::Integer to round to the nearest integer

Console Commands

sk_find

Syntax: sk_find <search_term> [filter] Finds a previously defined skill variable using partial, case-sensitive name matching and prints the candidates along with their current values. Use sk_find * to list all defined variables. The optional filter argument restricts which variables are checked:
FilterBehavior
allChecks all variables (default)
networkedonlyChecks only variables marked as networked

sk_set

Syntax: sk_set <name> <value> Sets a skill variable to the given value at runtime. If the variable does not already exist, it is created.

Migration Tool: Skill2Json

The Skill2Json tool converts original Half-Life skill.cfg files to the Unified SDK skill.json format. It is located in the mod installation’s tools directory.
dotnet path/to/Skill2Json.dll <filename> [--output-filename <output-filename>]

Comparison: Old System vs. New System

Adding a new skill variable in the original Half-Life required six separate steps:1. Add three lines to skill.cfg:
"sk_my_variable1" "10"
"sk_my_variable2" "10"
"sk_my_variable3" "10"
2. Add three cvar definitions to game.cpp:
cvar_t sk_my_variable1 = {"sk_my_variable1", "0"};
cvar_t sk_my_variable2 = {"sk_my_variable2", "0"};
cvar_t sk_my_variable3 = {"sk_my_variable3", "0"};
3. Register all three cvars in GameDLLInit:
CVAR_REGISTER(&sk_my_variable1);
CVAR_REGISTER(&sk_my_variable2);
CVAR_REGISTER(&sk_my_variable3);
4. Add a field to skilldata_t:
float myVariable;
5. Synchronize the field with the cvar in RefreshSkillData:
gSkillData.myVariable = GetSkillCvar("sk_my_variable");
6. Optionally override the variable for multiplayer in CHalfLifeMultiplay::RefreshSkillData, then use it:
pev->health = gSkillData.myVariable;

Build docs developers (and LLMs) love