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 an event driven fashion.
In Hammer, Entity scripts are assigned by adding the script file name, or file path when its in another folder within the scripts/vscripts folder, to the Entity Scripts (without SmartEdit, the
vscriptskey) KeyValue 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 into the entity by specifying multiple scripts in the Entity Scripts keyvalue, which differs from the
RunScriptFileinput, since it just loads into the root script scope[confirm]. When defining additional scripts, make sure all of the script names are separated by a blank space.
The option to use when you need to make Entity Scripts while a game is running; CBaseEntity provides the methods
.GetScriptScope()for editing Entity Scripts on the spot. The former creates a script scope for an entity if it doesn't exist, and returns true if it either one exists or one is created sucessfully; The latter returns a table containing everything in the script scope, if the script scope exists, or it returns nothing.
Since the scripting environment consists of associative arrays, or tables, that are nested inside each other, its why using
.GetScriptScope()returns a table.
Here is an example Entity Script being created, and put into players:
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;
_<uniqueID>_<entityname>. All entities only start with a script scope when they have a script attached to it, so during game runtime, always ensure the script scope is created with the CBaseEntity
.ValidateScriptScope()method. The script always has the variable
self defined, pointing to the script handle of the entity owning the script.
An Entity Script has a
self (Source 1) or
thisEntity (Source 2) reference to the script handle of the entity owning it, allowing the script easy access to control the entity through its class methods.
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.
When multiple scripts are loaded from the
vscripts keyvalue, the
OnPostSpawn() will be chained so that eventual versions present in either or both scripts are called.
Each entity supports a single thinker function, by default called every 0.1 seconds. The think function can only be set by the Think Function entity keyvlaue (without SmartEdit, the
thinkfunctionkey), or with the method. In however, The
AddThinkToEnt()function can be used to assign a function of its own Entity Script as a think function.
The think interval can be adjusted by returning a floating point value from the function, which is intepreted as seconds. You can set any value, but it will be limited by the server tick rate; A tick rate of 30 makes it that the true lowest value possible is 0.0333... seconds.
Example script of a think function:
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, and pre-defined 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.