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 separateDocumentation 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.
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:Skill Levels
| Level | Index |
|---|---|
| Easy | 1 |
| Medium | 2 |
| Hard | 3 |
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++, callGetSkillFloat with the variable name:
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 insideServerLibrary::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
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
-1 are clamped to -1.
Adding Multiple Constraints
Constraint Reference
| Name | Purpose |
|---|---|
Minimum | Minimum allowed value; values below this are clamped up |
Maximum | Maximum allowed value; values above this are clamped down |
Networked | When true, the value is sent to clients so that client-side code can access it |
Type | Type 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:
| Filter | Behavior |
|---|---|
all | Checks all variables (default) |
networkedonly | Checks 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
TheSkill2Json 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.
Comparison: Old System vs. New System
- Old System (Half-Life)
- New System (Unified SDK)
Adding a new skill variable in the original Half-Life required six separate steps:1. Add three lines to 2. Add three cvar definitions to 3. Register all three cvars in 4. Add a field to 5. Synchronize the field with the cvar in 6. Optionally override the variable for multiplayer in
skill.cfg:game.cpp:GameDLLInit:skilldata_t:RefreshSkillData:CHalfLifeMultiplay::RefreshSkillData, then use it: