About:- Heres an example plugin for returning values from a VScript code for use within SourcePawn.
- I cannot find any other good method for returning strings from VScript code.
- This uses a ConVar to transfer the data instantaneously.
- ConVars are limited to 255 bytes max length.
- Also the code max length is 255 but I have not tested.
- Remove the <RETURN> </RETURN> if statement from the stock for optimization if not required.
Stock:
PHP Code:
// ====================================================================================================
// START
// ====================================================================================================
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
ConVar gCvarBuffer;
public void OnPluginStart()
{
gCvarBuffer = CreateConVar("sm_vscript_return", "", "Buffer used to return vscript values. Do not use.");
}
// ====================================================================================================
// FUNCTION
// ====================================================================================================
/**
* Runs a single line of VScript code and returns values from it.
*
* @param code The code to run.
* @param buffer Buffer to copy to.
* @param maxlength Maximum size of the buffer.
* @return True on success, false otherwise.
* @error Invalid code.
*/
stock bool GetVScriptOutput(char[] code, char[] buffer, int maxlength)
{
static int logic = INVALID_ENT_REFERENCE;
if( logic == INVALID_ENT_REFERENCE || !IsValidEntity(logic) )
{
logic = EntIndexToEntRef(CreateEntityByName("logic_script"));
if( logic == INVALID_ENT_REFERENCE || !IsValidEntity(logic) )
SetFailState("Could not create 'logic_script'");
DispatchSpawn(logic);
}
// Return values between <RETURN> </RETURN>
int pos = StrContains(code, "<RETURN>");
if( pos != -1 )
{
strcopy(buffer, maxlength, code);
ReplaceString(buffer, maxlength, "</RETURN>", ");");
ReplaceString(buffer, maxlength, "<RETURN>", "Convars.SetValue(\"sm_vscript_return\", ");
}
else
{
Format(buffer, maxlength, "Convars.SetValue(\"sm_vscript_return\", \"\" + %s + \"\");", code);
}
// Run code
SetVariantString(buffer);
AcceptEntityInput(logic, "RunScriptCode");
AcceptEntityInput(logic, "Kill");
// Retrieve value and return to buffer
gCvarBuffer.GetString(buffer, maxlength);
gCvarBuffer.SetString("");
if( buffer[0] == '\x0')
return false;
return true;
}
Examples:
PHP Code:
// L4D2 VScript examples:
// Execute a single code block, avoid adding a semicolon ; at the end of the code statement. eg:
GetVScriptOutput("Director.GetGameMode()", buffer, maxlength);
// Returns for example "versus"
// Get flow through map
float vPos[3];
GetClientAbsOrigin(client, vPos);
Format(buffer, sizeof buffer, "GetFlowDistanceForPosition(Vector(%f, %f, %f))", vPos[0], vPos[1], vPos[2]);
GetVScriptOutput(buffer, buffer, sizeof buffer);
// Returns a float from 0 to GetMaxFlowDistance() for example "3550.3"
// Example stock: GetRandomPlayerName()
// Execute several code blocks, must wrap the section you want to return within <RETURN> </RETURN> otherwise the script will fail.
// Omit the trailing semicolon within <RETURN> block.
GetVScriptOutput("local player = null; while(player = Entities.FindByClassname(player, \"player\")) { if(player.IsSurvivor()) { <RETURN>player.GetName()</RETURN> } }", buffer, maxlength);
Changes:
Code:
0.1 (29-Jun-2019)
- Initial release.