Every game with VScript capability supports attaching scripts to server-side entities. These Entity scripts can be used for adding new functionality or logic to entities, and are a convenient way of scripting in a event driven fashion.
Entity scripts are assigned by adding the script file name to the Entity Scripts (
vscripts) attribute of an entity. The script is executed when the entity spawns, and loads into a script scope specific to each entity instance. The script and all the variables and functions can be accessed through the entity, and remain available for the duration of the entity's lifetime.
Additional scripts can be loaded by specifying multiple scripts in the Entity Scripts attribute, or using the
RunScriptFile Input. All scripts that are run on the same entity will load into the same script scope, overwriting any identical variables and functions. Variables and functions can also be inserted into the script scope table directly with other scripts.
To do: How are multiple scripts specified?
The script scope is placed directly in the root table, using a key made up of an unique identifier followed by the entity name or class name;
_<unique ID>_<entity name>. If no script has been run on the entity, a script scope can be manually created by using the
The script always has the variable
self defined, pointing to the script handle of the entity owning the script.
Entities have the ability to call functions in their script scope from the C++ side. Common entity classes have predefined function calls programmed into them to occur at certain events, allowing scripts to execute code. For example, creating a function called
Precache() in an entity script will call that function right after the entity spawns, allowing the script to precache any custom assets. These functions do not need to be registered, and are always called if if one with the right name exist. Please see the API documentation for your game to find out what hook functions are available for each class.
Each entity supports a single thinker function, by default called every 0.1 seconds. The think function can be set either with the Think Function (
thinkfunction) entity attribute, or with the
The think interval can be adjusted by returning a floating point value from the function. This value is give in seconds. It is limited by the server tick rate, so for example for a tick rate of 30, the lowest value possible is 0.333 seconds.
In contrast to Source, the script scopes of entity scripts in Source 2 are not accessible from the root table. Entities in Source 2 has both public and private script scopes. Entity scripts get loaded into the private script scope. To do: How are public script scopes used?
The script always has the variable
thisEntity defined, pointing to the script handle of the entity owning the script.
CBaseEntity::ConnectOutput() method seems to be non-functional in Source 2. To call functions on entity output, the output can instead be bound to fire the
CallScriptFunction input on the same entity. The
CallScriptFunction input passes on the activator and caller entities in a table to the first argument of the called function.
Example Lua script referencing the passed handles.
-- To use this, add a output from an entity (like a trigger) to the CallScriptFunction input of the entity with the script, setting the value to SetActivatorColor. function SetActivatorColor(params) if params.activator then -- Tints the activating entity red. params.activator:SetRenderColor(255, 0, 0) print(thisEntity:GetDebugName() .. ": Activated by " .. params.activator:GetDebugName()) end print(thisEntity:GetDebugName() .. ": Called by " .. params.caller:GetDebugName()) end