SourceMod plugin that exposes many VScript features to make use of it.
Currently supports the following games:
- Counter Strike: Source
- Day of Defeat: Source
- Half-Life 2: Deathmatch
- Left 4 Dead 2
- Team Fortress 2
All builds can be found in releases page, auto-built on every commits done in main branch.
- At least SourceMod version 1.12.0.6924
- sourcescramble
vscript.inc and vscript_test.sp should give enough documentation on how to make use of it, but below gives some basic examples on common features:
Compiles and executes a script code with params and returns, helpful when RunScriptCode input does not support receiving returns.
publicvoidOnAllPluginsLoaded()
{
HSCRIPTscript=VScript_CompileScript("printl(\"Wow a message!\"); return 4242; function PrintMessage(param) { printl(param) }");
VScriptExecuteexecute=newVScriptExecute(script);
execute.Execute();
intret=execute.ReturnValue;
PrintToServer("%d", ret); // Expected to print 4242deleteexecute;
// Call a PrintMessage functionexecute=newVScriptExecute(HSCRIPT_RootTable.GetValue("PrintMessage"));
execute.SetParamString(1, FIELD_CSTRING, "Hello!");
execute.Execute();
deleteexecute;
script.ReleaseScript();
}This allows to directly call or detour a function without needing to manually get gamedata signatures. Parameters and returns are automatically set to the handle.
Handleg_SDKCallGetAngles;
publicvoidOnAllPluginsLoaded()
{
VScriptFunctionfunc=VScript_GetClassFunction("CBaseEntity", "GetAngles");
g_SDKCallGetAngles=func.CreateSDKCall();
DynamicDetourdetour=func.CreateDetour();
detour.Enable(Hook_Post, Detour_GetAngles);
RegConsoleCmd("sm_getangles", Command_GetAngles);
}
ActionCommand_GetAngles(intclient, intargs)
{
floatangles[3];
SDKCall(g_SDKCallGetAngles, client, angles);
ReplyToCommand(client, "result: x = %.2f, y = %.2f, z = %.2f", angles[0], angles[1], angles[2]);
returnPlugin_Handled;
}
MRESReturnDetour_GetAngles(intentity, DHookReturnret)
{
floatangles[3];
ret.GetVector(angles);
PrintToServer("entity %d angles: x = %.2f, y = %.2f, z = %.2f", entity, angles[0], angles[1], angles[2]);
returnMRES_Ignored;
}Creates a new native function where scripts can make use of it. Does nothing by default but can use VScriptFunction.CreateDetour above to do actions and set return.
VScriptFunctiong_NewFunction;
publicvoidOnAllPluginsLoaded()
{
// Create a new function, or get an existing one if name already existsg_NewFunction=VScript_CreateGlobalFunction("NewFunction");
g_NewFunction.SetParam(1, FIELD_FLOAT);
g_NewFunction.Return=FIELD_INTEGER;
g_NewFunction.SetFunctionEmpty();
// If plugin were to be lateloaded and that script vm is already initialized, just manually call it.if (VScript_IsScriptVMInitialized())
VScript_OnScriptVMInitialized();
}
publicvoidVScript_OnScriptVMInitialized()
{
// Global function need to be registered everytime g_pScriptVM has been reset, which happens right before this forwardg_NewFunction.Register();
}VScript uses FIELD_HSCRIPT to interact with entities, so VScript_EntityToHScript and VScript_HScriptToEntity are helpful functions to convert between entity index and hscript object to manage with it.
In L4D2 linux, attempting to reset g_pScriptVM will eventually cause a crash. For now a plugin prevents any attempts to reset such, meaning that not everything may work properly until a mapchange occurs.