Overview
Garry’s Mod uses a “scripted class” pattern. You define a global table, such as ENT or SWEP, in a specific file location, and GMod registers it as a class. GLuaLS detects these classes and provides:
- Class registration including inheritance
- Synthesis of
NetworkVar getter/setter pairs
- Synthesis of
AccessorFunc getter/setter pairs
- Better completions and type checking for scripted class code
Automatic detection
GLuaLS detects scripted classes by file path. It treats any file under a recognized directory as defining the matching table. For example:
| Directory pattern | Class table | Base class |
|---|
lua/entities/**/ | ENT | Entity |
lua/weapons/**/ | SWEP | Weapon |
lua/effects/**/ | EFFECT | (none) |
GLuaLS types the detected class table with the base class’s methods and fields, so you get completions and type checking without annotations.
You can adjust this table in settings.
AccessorFunc synthesis
AccessorFunc(table, member, name, ...) generates getter and setter methods. GLuaLS detects these calls and synthesizes the methods:
AccessorFunc(ENT, "m_bOrient", "Orient", FORCE_BOOL)
-- GLuaLS synthesizes:
-- ENT:GetOrient() -> boolean
-- ENT:SetOrient(value: boolean) -> nil
Use the ---@accessorfunc annotation for custom getters and setters. See @accessorfunc for details.
NetworkVar synthesis
ENT:NetworkVar(type, slot, name, ...) generates entity accessors. GLuaLS detects these calls and synthesizes matching methods:
function ENT:SetupDataTables()
self:NetworkVar("Int", 0, "Health")
self:NetworkVar("Bool", 1, "Active")
self:NetworkVar("String", 2, "Name")
end
-- GLuaLS synthesizes:
-- ENT:GetHealth() -> number
-- ENT:SetHealth(value: number) -> nil
-- ENT:GetActive() -> boolean
-- ENT:SetActive(value: boolean) -> nil
-- ENT:GetName() -> string
-- ENT:SetName(value: string) -> nil
You get completions and type checking for generated accessors without manual annotations.
Supported NetworkVar types
| NetworkVar type | Getter/setter type |
|---|
"Int" | integer |
"UInt" | integer |
"Float" | number |
"Double" | number |
"Bool" | boolean |
"String" | string |
"Entity" | Entity |
"Vector" | Vector |
"Angle" | Angle |
"Color" | Color |
Base class inheritance
Scripted classes in GMod inherit from base classes. GLuaLS understands this chain and suggests inherited methods. The scripted class table also gets the standard base type for that scope, such as Entity, Weapon, or Tool. DEFINE_BASECLASS(...) and values like ENT.Base can refine that type further.
function ENT:Use(ply)
self:EmitSound("...") -- inherited from Entity / base class chain ✅
ply:ChatPrint("Hello") -- Player method ✅
end
For gamemodes that derive from another gamemode, such as DarkRP deriving from Sandbox, GLuaLS adds the parent’s folder as a library. See Gamemode inheritance to configure or disable this.
Hook overrides in scripted classes
GLuaLS treats functions defined in a scripted class table as engine hook overrides for that class:
function ENT:Think() -- override of ENTITY:Think hook
function ENT:Draw() -- override of ENTITY:Draw hook
function ENT:OnRemove() -- override of ENTITY:OnRemove hook
Completions suggest the correct signature for each override.
Class Explorer integration
The VS Code Class Explorer lists detected scripted classes. You can browse groups, such as entities, weapons, effects, and custom scopes, and jump to class definitions.
Class grouping and labels come from gmod.scriptedClassScopes.include.
Scaffolding integration
Scripted class scopes also control class scaffolding. Each scope can define scaffold output files with scaffold.files and a rootDir in gmod.scriptedClassScopes.include.
You can create new classes with your own template layout while GLuaLS keeps class analysis, explorer grouping, and generated files in sync.
See GMod settings for all supported fields.
Creating a new class
- Open the Class Explorer in the sidebar.
- Find the group you want, such as Entities.
- Click the + button next to that group.
- Enter the class name.
- The VS Code extension creates the files and opens the main file.
Built-in templates
The VS Code extension includes built-in templates for the standard scripted class types:
| Class type | Generated files |
|---|
| Entity | shared.lua, init.lua, cl_init.lua |
| Weapon (SWEP) | shared.lua |
| Effect | your_effect_name.lua |
| Scripted Tool (STOOL) | your_tool_name.lua |
Custom class scopes
If you use a non-standard directory structure or custom class types, configure GLuaLS to recognize them:
Use the settings menu instead of editing the JSON file directly. This helps you avoid config mistakes.
{
"gmod": {
"scriptedClassScopes": {
"include": [
{
"id": "my_panels",
"label": "Panels",
"classGlobal": "PANEL",
"path": ["panels"],
"include": ["lua/panels/**"],
"rootDir": "lua/panels"
}
]
}
}
}
Fields
| Field | Description |
|---|
id | Unique identifier for this class scope |
label | Display name in the Class Explorer sidebar |
classGlobal | The global table name used in scripts (e.g., ENT, SWEP, PANEL) |
path | Path segments used for display grouping in the Class Explorer |
include | Glob patterns matching files that belong to this class type |
rootDir | Root directory for scaffolded files |
icon | VS Code icon ID shown in the Class Explorer (e.g., symbol-class) |
Disabling scripted class inference
To disable a built-in scripted class scope, add an override with the same id and set "disabled": true.
{
"gmod": {
"scriptedClassScopes": {
"include": [
{
"id": "effects",
"disabled": true
}
]
}
}
}