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 hard-coded NPC classification system from the original game with a fully data-driven one that level designers and mod authors can customise. Rather than having relationships between NPC types compiled into the game binary, all classification relationships are defined in a JSON configuration file that can be swapped out on a per-map basis. Classifications are comparable to factions. For example, the human_passive classification (scientists) fears human_military (human grunts) and will flee from them, while human_military dislikes human_passive and will attack on sight. Any of these relationships can be changed or new classifications added without touching C++ code.
The entity classifications system uses the logger named ent.classify. Enable it at the appropriate log level to trace classification lookups and relationship resolution during development.

Configuration File

The default classification configuration is loaded from cfg/default_entity_classes.json. A custom file can be specified in the map configuration file using the EntityClassifications section, allowing different maps or campaigns to use entirely different faction setups. Only one configuration file is active at a time.

Relationship Types

Each classification defines how it relates to every other classification through one of the following relationship types.
RelationshipBehaviour
allyFriends. A good alternative to none when the relationship should be positive.
fearThe NPC will flee from members of this classification.
noneComplete disregard — the NPC ignores members of this classification.
dislikeThe NPC will attack members of this classification when it sees them.
hateThe NPC will attack members of this classification in preference to any dislike targets.
nemesisThe NPC will always attack members of this classification regardless of any other targets.
The default relationship from any classification to any other is none unless explicitly specified or overridden with DefaultRelationshipToTarget.
The special classification none is always present and should never have relationships defined for it. Entities rely on it to be completely ignored.

JSON Syntax

A classification configuration file is a JSON object. Each key is a classification name and its value is an object with two optional fields:
FieldDescription
DefaultRelationshipToTargetSets the default relationship this classification has towards all other classifications. Useful when a faction is hostile or fearful of everything except specific exceptions.
RelationshipsAn object mapping individual classification names to specific relationship types, overriding the default.

Minimal Example

The insect classification below fears everything by default, but has none (disregard) towards a handful of classifications it coexists with:
"insect": {
    "DefaultRelationshipToTarget": "fear",
    "Relationships": {
        "alien_military": "none",
        "insect": "none",
        "player_bioweapon": "none",
        "alien_bioweapon": "none",
        "race_x": "none"
    }
}

Full Example

Below is an excerpt from a complete classification file showing several factions with their relationships. Classifications not listed in Relationships fall back to DefaultRelationshipToTarget, or none if that is also absent.
{
    "none": {},

    "machine": {
        "Relationships": {
            "player": "dislike",
            "human_passive": "dislike",
            "human_military": "none",
            "alien_military": "dislike",
            "alien_passive": "dislike",
            "alien_monster": "dislike",
            "alien_prey": "dislike",
            "alien_predator": "dislike",
            "player_ally": "dislike",
            "player_bioweapon": "dislike",
            "alien_bioweapon": "dislike",
            "human_military_ally": "dislike",
            "race_x": "dislike"
        }
    },

    "player": {
        "Relationships": {
            "machine": "dislike",
            "human_military": "dislike",
            "alien_military": "dislike",
            "alien_passive": "dislike",
            "alien_monster": "dislike",
            "alien_prey": "dislike",
            "alien_predator": "dislike",
            "player_bioweapon": "dislike",
            "alien_bioweapon": "dislike",
            "race_x": "dislike"
        }
    },

    "human_passive": {
        "Relationships": {
            "player": "ally",
            "human_passive": "ally",
            "human_military": "hate",
            "alien_military": "hate",
            "alien_monster": "hate",
            "alien_prey": "dislike",
            "alien_predator": "dislike",
            "player_ally": "ally",
            "human_military_ally": "dislike",
            "race_x": "hate"
        }
    }
}

Per-Entity Classification Overrides

Individual entity instances can override their classification using keyvalues, without needing to change the global configuration file.
KeyvalueDescription
classificationOverrides this entity’s classification with the named classification from the config file.
child_classificationOverrides the classification of entities spawned by this entity. Supports !owner and !owner_or_default.
is_player_allyShorthand override for the entity’s relationship to the player. 0 = default, 1 = always hostile, 2 = always friendly.
Use is_player_ally when you want a single NPC to be friendly or hostile to the player without changing its faction-wide relationships. Use classification when you want a full faction change.

See Also

Build docs developers (and LLMs) love