L4D2 VScript Support
Language support for Left 4 Dead 2 VScript in Visual Studio Code, with the full
L4D2 script API built in.
L4D2 embeds Squirrel 3.0.4 and exposes its own set of classes, globals,
constants and Director options. This extension parses Squirrel properly (no
regex heuristics) and answers editor requests from both your own code and a
generated snapshot of the engine API.
Features
Completion
- Locals, parameters, and everything the workspace publishes into the root table
- Engine globals, classes, instances (
Director, Entities, NetProps, …) and
constants (ZOMBIE_TANK, DMG_BULLET, HUD_PRINTTALK, …)
- Members resolved through the class hierarchy, so a
CTerrorPlayer handle
offers GetOrigin from CBaseEntity
- Squirrel standard-library delegates on the inferred type:
array values offer
append/sort/filter, string values offer slice/find/tolower
DirectorOptions keys inside a DirectorOptions, SessionOptions,
MutationOptions or MapOptions table
- String literals in the argument position that expects them: entity classnames,
network property names, game event names, and
IncludeScript paths
function OnGameEvent_<tab> expands to any of the 333 known game events
Navigation and editing
- Hover with the wiki documentation, the signature, and a link to the source page
- Signature help, including the overloads the wiki documents
- Go to definition, go to type definition, find references, rename
- Document outline, workspace symbol search, document highlights
- Semantic highlighting that distinguishes engine symbols from your own
- Inlay parameter-name hints, folding, smart selection expansion
IncludeScript("…") and DoIncludeScript("…") become clickable links
Diagnostics
- Syntax errors, reported without giving up on the rest of the file
- Unused locals and parameters, unreachable code, duplicate
case labels,
duplicate parameter names
local x <- 1, which creates a slot rather than a local
- Unresolved identifiers
- Argument-count mismatches against functions declared in your workspace
- Calls to engine functions the wiki records as non-functional in L4D2
- Symbols carried over from other Source VScript branches that L4D2 does not
have:
EntFireByHandle, Constants.*, vargc, __KeyValueFromFloat
\u/\U escapes, which postdate Squirrel 3.0.4
- Quick fixes for the common ones
What the engine API covers
|
|
| Global functions |
225 |
| Classes |
32, with 449 methods |
| Constants and instances |
200+ |
DirectorOptions keys |
148 |
| Game events |
333, with field lists |
| Entity classnames |
594 |
The data is generated from the Valve Developer Community wiki and the
AlliedModders event reference, plus the Squirrel 3.0.4 standard library.
Run npm run generate to rebuild it.
Type hints
Type inference covers literals, constructors, engine return types, and member
chains. Where it cannot tell, a documentation comment settles it:
/** @type {CTerrorPlayer} */
local target = null;
/**
* Teleport a survivor to a spawn point.
*
* @param {CTerrorPlayer} player The survivor to move.
* @param {Vector} destination Where to put them.
* @returns {bool} Whether the move succeeded.
*/
function TeleportSurvivor(player, destination)
{
// `player.` now completes CTerrorPlayer members.
}
Settings
| Setting |
Default |
Description |
l4d2VScript.diagnostics.enable |
true |
Master switch for diagnostics. |
l4d2VScript.diagnostics.unusedLocals |
true |
Report locals and parameters that are never read. Prefix a name with _ to opt out. |
l4d2VScript.diagnostics.unreachableCode |
true |
Report statements that can never run. |
l4d2VScript.diagnostics.undefinedGlobals |
true |
Report identifiers that resolve nowhere. |
l4d2VScript.diagnostics.argumentCount |
true |
Report calls with the wrong number of arguments. |
l4d2VScript.diagnostics.deprecatedAndBuggy |
true |
Report engine functions documented as broken. |
l4d2VScript.inlayHints.parameterNames |
true |
Show parameter names at call sites. |
l4d2VScript.inlayHints.parameterTypes |
false |
Show parameter types instead of names. |
l4d2VScript.completion.stringLiterals |
true |
Suggest L4D2 string literals inside string arguments. |
l4d2VScript.workspace.scriptRoots |
["scripts/vscripts"] |
Roots used to resolve IncludeScript paths. |
l4d2VScript.workspace.maxFiles |
3000 |
Cap on indexed script files per workspace folder. |
Accuracy notes
Squirrel resolves free identifiers at run time through the table that owns the
running closure. Inside a class method, a table slot, or a function A::b()
definition, a bare name can legitimately refer to something no static analysis
can see. The unresolved-identifier check is therefore suppressed in those
positions rather than guessing.
The wiki signatures do not mark optional parameters and are occasionally
incomplete, so argument counts are only enforced against declarations the
extension can actually read — in your file or elsewhere in the workspace.
Engine signatures still drive hover and signature help.
Development
npm install
npm run generate # rebuild the API data, grammar and icon
npm run watch # incremental build
npm test # unit tests
Two extra checks run the analyser over a corpus of real scripts placed in
corpus/ (Valve's decompiled scripts, VSLib, Left4Lib and similar):
npm run check-corpus # every file must parse without a syntax error
npm run check-diagnostics # summarise warnings, to watch the false-positive rate
Press F5 to launch an Extension Development Host.
Credits
- The Valve Developer Community for the L4D2 VScript reference.
- The AlliedModders wiki for the game event reference.
- Inspired by TF2 VScript Support
by ocet247, which does the same job for Team Fortress 2.
Documentation text bundled with the extension comes from the Valve Developer
Community wiki and is used under CC BY-NC-SA 2.5. The extension code is MIT
licensed.