Hello, wondering if there is a sound precaching limit for l4d2? Read that it's 512 files apparently for most source games. Wrote this plugin which plays survivor sounds when they vocalize through the radial menu. It precaches about >= 137 wav files in total. The plugin itself is fully functional however it seems to cause some serious sound issues ( distorting/ etc) on the server when used for not long. Plugin uses 'sceneprocessor' to work.
yes i know theres probably bad checks, this was while ago.
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <sceneprocessor>
int iSkippedFrames;
char sVocalizeScene[MAXPLAYERS+1][MAX_VOCALIZE_LENGTH];
bool bSceneHasInitiator[MAXPLAYERS+1], bScenesUnprocessed, bUnvocalizedCommands, bJailbreakVocalize,
bIsL4D;
float fStartTimeStamp, fVocalizePreDelay[MAXPLAYERS+1], fVocalizePitch[MAXPLAYERS+1];
Handle hSceneStageForward, hVocalizeCommandForward;
ArrayList alVocalize;
ArrayStack asScene;
enum SceneData
{
SceneStages:ssDataBit,
bool:bInFakePostSpawn,
Float:fTimeStampData,
iActorData,
iInitiatorData,
String:sFileData[MAX_SCENEFILE_LENGTH],
String:sVocalizeData[MAX_VOCALIZE_LENGTH],
Float:fPreDelayData,
Float:fPitchData
};
new nSceneData[2048][SceneData];
int iScenePlaying[MAXPLAYERS+1], iVocalizeTick[MAXPLAYERS+1], iVocalizeInitiator[MAXPLAYERS+1];
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
EngineVersion evGame = GetEngineVersion();
if (evGame == Engine_Left4Dead)
{
bIsL4D = true;
}
else if (evGame != Engine_Left4Dead2)
{
strcopy(error, err_max, "[SP] Plugin Supports L4D And L4D2 Only!");
return APLRes_Failure;
}
CreateNative("GetSceneStage", SP_GetSceneStage);
CreateNative("GetSceneStartTimeStamp", SP_GetSceneStartTimeStamp);
CreateNative("GetActorFromScene", SP_GetSceneActor);
CreateNative("GetSceneFromActor", SP_GetActorScene);
CreateNative("GetSceneInitiator", SP_GetSceneInitiator);
CreateNative("GetSceneFile", SP_GetSceneFile);
CreateNative("GetSceneVocalize", SP_GetSceneVocalize);
CreateNative("GetScenePreDelay", SP_GetScenePreDelay);
CreateNative("SetScenePreDelay", SP_SetScenePreDelay);
CreateNative("GetScenePitch", SP_GetScenePitch);
CreateNative("SetScenePitch", SP_SetScenePitch);
CreateNative("CancelScene", SP_CancelScene);
CreateNative("PerformScene", SP_PerformScene);
CreateNative("PerformSceneEx", SP_PerformSceneEx);
RegPluginLibrary("sceneprocessor");
return APLRes_Success;
}
public SP_GetSceneStage(Handle plugin, int numParams)
{
if (numParams == 0)
{
return _:SceneStage_Unknown;
}
int scene = GetNativeCell(1);
if (scene < 1 || scene > 2048 || !IsValidEntity(scene))
{
return _:SceneStage_Unknown;
}
return _:nSceneData[scene][ssDataBit];
}
public SP_GetSceneStartTimeStamp(Handle plugin, int numParams)
{
if (numParams == 0)
{
return _:0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return _:0.0;
}
return _:nSceneData[scene][fTimeStampData];
}
public int SP_GetActorScene(Handle plugin, int numParams)
{
if (numParams == 0)
{
return INVALID_ENT_REFERENCE;
}
int iActor = GetClientOfUserId(GetNativeCell(1));
if (iActor < 1 || iActor > MaxClients || !IsClientInGame(iActor) || GetClientTeam(iActor) != 2 || !IsPlayerAlive(iActor))
{
return INVALID_ENT_REFERENCE;
}
return iScenePlaying[iActor];
}
public int SP_GetSceneActor(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
return nSceneData[scene][iActorData];
}
public int SP_GetSceneInitiator(Handle plugin, int numParams)
{
if (numParams == 0)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
return nSceneData[scene][iInitiatorData];
}
public int SP_GetSceneFile(Handle plugin, int numParams)
{
if (numParams != 3)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
int len = GetNativeCell(3);
int bytesWritten;
SetNativeString(2, nSceneData[scene][sFileData], len, _, bytesWritten);
return bytesWritten;
}
public int SP_GetSceneVocalize(Handle plugin, int numParams)
{
if (numParams != 3)
{
return 0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return 0;
}
int len = GetNativeCell(3);
int bytesWritten;
SetNativeString(2, nSceneData[scene][sVocalizeData], len, _, bytesWritten);
return bytesWritten;
}
public SP_GetScenePreDelay(Handle plugin, int numParams)
{
if (numParams == 0)
{
return _:0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return _:0.0;
}
return _:nSceneData[scene][fPreDelayData];
}
public SP_SetScenePreDelay(Handle plugin, int numParams)
{
if (numParams != 2)
{
return;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return;
}
float fPreDelay = GetNativeCell(2);
SetEntPropFloat(scene, Prop_Data, "m_flPreDelay", fPreDelay);
nSceneData[scene][fPreDelayData] = fPreDelay;
}
public SP_GetScenePitch(Handle plugin, int numParams)
{
if (numParams == 0)
{
return _:0.0;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return _:0.0;
}
return _:nSceneData[scene][fPitchData];
}
public SP_SetScenePitch(Handle plugin, int numParams)
{
if (numParams != 2)
{
return;
}
int scene = GetNativeCell(1);
if (!IsValidScene(scene))
{
return;
}
float fPitch = GetNativeCell(2);
SetEntPropFloat(scene, Prop_Data, "m_fPitch", fPitch);
nSceneData[scene][fPitchData] = fPitch;
}
public SP_CancelScene(Handle plugin, int numParams)
{
if (numParams == 0)
{
return;
}
int scene = GetNativeCell(1);
if (scene < 1 || scene > 2048 || !IsValidEntity(scene))
{
return;
}
SceneStages ssBit = nSceneData[scene][ssDataBit];
if (ssBit == SceneStage_Unknown)
{
return;
}
else if (ssBit == SceneStage_Started || (ssBit == SceneStage_SpawnedPost && nSceneData[scene][bInFakePostSpawn]))
{
AcceptEntityInput(scene, "Cancel");
}
else if (ssBit != SceneStage_Cancelled && ssBit != SceneStage_Completion && ssBit != SceneStage_Killed)
{
AcceptEntityInput(scene, "Kill");
}
}
public SP_PerformScene(Handle plugin, int numParams)
{
if (numParams < 2)
{
return;
}
int client = GetClientOfUserId(GetNativeCell(1));
if (client < 1 || client > MaxClients || !IsClientInGame(client) || GetClientTeam(client) != 2 || !IsPlayerAlive(client))
{
return;
}
char sVocalize[MAX_VOCALIZE_LENGTH], sFile[MAX_SCENEFILE_LENGTH];
float fPreDelay = DEFAULT_SCENE_PREDELAY, fPitch = DEFAULT_SCENE_PITCH;
int iInitiator = SCENE_INITIATOR_PLUGIN;
if (GetNativeString(2, sVocalize, MAX_VOCALIZE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown Vocalize Parameter!");
return;
}
if (numParams >= 3)
{
if (GetNativeString(3, sFile, MAX_SCENEFILE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown File Parameter!");
return;
}
}
if (numParams >= 4)
{
fPreDelay = GetNativeCell(4);
}
if (numParams >= 5)
{
fPitch = GetNativeCell(5);
}
if (numParams >= 6)
{
iInitiator = GetNativeCell(6);
}
Scene_Perform(client, sVocalize, sFile, fPreDelay, fPitch, iInitiator);
}
public SP_PerformSceneEx(Handle plugin, int numParams)
{
if (numParams < 2)
{
return;
}
int client = GetClientOfUserId(GetNativeCell(1));
if (client < 1 || client > MaxClients || !IsClientInGame(client) || GetClientTeam(client) != 2 || !IsPlayerAlive(client))
{
return;
}
char sVocalize[MAX_VOCALIZE_LENGTH], sFile[MAX_SCENEFILE_LENGTH];
float fPreDelay = DEFAULT_SCENE_PREDELAY, fPitch = DEFAULT_SCENE_PITCH;
int iInitiator = SCENE_INITIATOR_PLUGIN;
if (GetNativeString(2, sVocalize, MAX_VOCALIZE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown Vocalize Parameter!");
return;
}
if (numParams >= 3)
{
if (GetNativeString(3, sFile, MAX_SCENEFILE_LENGTH) != SP_ERROR_NONE)
{
ThrowNativeError(SP_ERROR_NATIVE, "Unknown File Parameter!");
return;
}
}
if (numParams >= 4)
{
fPreDelay = GetNativeCell(4);
}
if (numParams >= 5)
{
fPitch = GetNativeCell(5);
}
if (numParams >= 6)
{
iInitiator = GetNativeCell(6);
}
Scene_Perform(client, sVocalize, sFile, fPreDelay, fPitch, iInitiator, true);
}
public Plugin myinfo =
{
name = "Scene Processor",
author = "Buster \"Mr. Zero\" Nielsen",
description = "Provides Forwards and Natives For Scenes' Manipulation.",
version = "1.33",
url = "https://forums.alliedmods.net/showthread.php?t=241585"
};
public void OnPluginStart()
{
hSceneStageForward = CreateGlobalForward("OnSceneStageChanged", ET_Ignore, Param_Cell, Param_Cell);
hVocalizeCommandForward = CreateGlobalForward("OnVocalizeCommand", ET_Hook, Param_Cell, Param_String, Param_Cell);
CreateConVar("sceneprocessor_version", "1.33", "Scene Processor Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD);
if (!bIsL4D)
{
ConVar spJailbreakVocalize = CreateConVar("sceneprocessor_jailbreak_vocalize", "1", "Enable/Disable Jailbreak Vocalizations", FCVAR_SPONLY|FCVAR_NOTIFY);
spJailbreakVocalize.AddChangeHook(OnSPCVarChanged);
bJailbreakVocalize = spJailbreakVocalize.BoolValue;
}
AddCommandListener(OnVocalizeCmd, "vocalize");
asScene = new ArrayStack();
alVocalize = new ArrayList(MAX_VOCALIZE_LENGTH);
for (int i = 1; i < 2049; i++)
{
if (IsValidEntity(i) && IsValidEdict(i))
{
SceneData_SetStage(i, SceneStage_Unknown);
}
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
ResetClientVocalizeData(i);
}
}
}
public void OnSPCVarChanged(ConVar cvar, const char[] sOldValue, const char[] sNewValue)
{
bJailbreakVocalize = cvar.BoolValue;
}
public Action OnVocalizeCmd(int client, const char[] command, int args)
{
if (client == 0 || args == 0)
{
return Plugin_Continue;
}
if (!IsClientInGame(client))
{
return Plugin_Handled;
}
char sVocalize[128];
GetCmdArg(1, sVocalize, sizeof(sVocalize));
if (!bIsL4D && args != 2)
{
if (bJailbreakVocalize)
{
JailbreakVocalize(client, sVocalize);
}
return Plugin_Handled;
}
int iTick = GetGameTickCount();
if (!bSceneHasInitiator[client] || (iVocalizeTick[client] > 0 && iVocalizeTick[client] != iTick))
{
iVocalizeInitiator[client] = client;
if (!bIsL4D && args > 1 && StrEqual(sVocalize, "smartlook", false))
{
char sTime[32];
GetCmdArg(2, sTime, sizeof(sTime));
if (StrEqual(sTime, "auto", false))
{
iVocalizeInitiator[client] = SCENE_INITIATOR_WORLD;
}
}
}
strcopy(sVocalizeScene[client], MAX_VOCALIZE_LENGTH, sVocalize);
iVocalizeTick[client] = iTick;
Action aResult = Plugin_Continue;
Call_StartForward(hVocalizeCommandForward);
Call_PushCell(client);
Call_PushString(sVocalize);
Call_PushCell(iVocalizeInitiator[client]);
Call_Finish(aResult);
return (aResult == Plugin_Stop) ? Plugin_Handled : Plugin_Continue;
}
public void OnPluginEnd()
{
RemoveCommandListener(OnVocalizeCmd, "vocalize");
}
public void OnMapStart()
{
iSkippedFrames = 0;
fStartTimeStamp = GetGameTime();
}
public void OnEntityCreated(int entity, const char[] classname)
{
if (entity < 1 || entity > 2048)
{
return;
}
if (StrEqual(classname, "instanced_scripted_scene"))
{
SDKHook(entity, SDKHook_SpawnPost, OnSpawnPost);
SceneData_SetStage(entity, SceneStage_Created);
}
}
public void OnSpawnPost(int entity)
{
int iActor = GetEntPropEnt(entity, Prop_Data, "m_hOwner");
nSceneData[entity][iActorData] = iActor;
char sFile[MAX_SCENEFILE_LENGTH];
GetEntPropString(entity, Prop_Data, "m_iszSceneFile", sFile, MAX_SCENEFILE_LENGTH);
strcopy(nSceneData[entity][sFileData], MAX_SCENEFILE_LENGTH, sFile);
nSceneData[entity][fPitchData] = GetEntPropFloat(entity, Prop_Data, "m_fPitch");
if (iActor > 0 && iActor <= MaxClients && IsClientInGame(iActor))
{
if (iVocalizeTick[iActor] == GetGameTickCount())
{
strcopy(nSceneData[entity][sVocalizeData], MAX_VOCALIZE_LENGTH, sVocalizeScene[iActor]);
nSceneData[entity][iInitiatorData] = iVocalizeInitiator[iActor];
nSceneData[entity][fPreDelayData] = fVocalizePreDelay[iActor];
nSceneData[entity][fPitchData] = fVocalizePitch[iActor];
}
ResetClientVocalizeData(iActor);
}
SetEntPropFloat(entity, Prop_Data, "m_fPitch", nSceneData[entity][fPitchData]);
SetEntPropFloat(entity, Prop_Data, "m_flPreDelay", nSceneData[entity][fPreDelayData]);
asScene.Push(entity);
bScenesUnprocessed = true;
HookSingleEntityOutput(entity, "OnStart", OnSceneStart_EntOutput);
HookSingleEntityOutput(entity, "OnCanceled", OnSceneCanceled_EntOutput);
SceneData_SetStage(entity, SceneStage_Spawned);
}
public void OnSceneStart_EntOutput(const char[] output, int caller, int activator, float delay)
{
if (caller < 1 || caller > 2048 || !IsValidEntity(caller))
{
return;
}
char sFile[MAX_SCENEFILE_LENGTH];
strcopy(sFile, MAX_SCENEFILE_LENGTH, nSceneData[caller][sFileData]);
if (strlen(sFile) == 0)
{
return;
}
nSceneData[caller][fTimeStampData] = GetEngineTime();
if (nSceneData[caller][ssDataBit] == SceneStage_Spawned)
{
nSceneData[caller][bInFakePostSpawn] = true;
SceneData_SetStage(caller, SceneStage_SpawnedPost);
}
if (nSceneData[caller][ssDataBit] == SceneStage_SpawnedPost)
{
int iActor = nSceneData[caller][iActorData];
if (iActor > 0 && iActor <= MaxClients && IsClientInGame(iActor))
{
iScenePlaying[iActor] = caller;
}
SceneData_SetStage(caller, SceneStage_Started);
}
}
public void OnSceneCanceled_EntOutput(const char[] output, int caller, int activator, float delay)
{
if (caller < 1 || caller > 2048 || !IsValidEntity(caller))
{
return;
}
for (int i = 1; i <= MaxClients; i++)
{
if (iScenePlaying[i] == caller)
{
iScenePlaying[i] = INVALID_ENT_REFERENCE;
break;
}
}
SceneData_SetStage(caller, SceneStage_Cancelled);
}
public void OnEntityDestroyed(int entity)
{
if (entity < 1 || entity > 2048 || !IsValidEdict(entity))
{
return;
}
char sEntityClass[64];
GetEdictClassname(entity, sEntityClass, sizeof(sEntityClass));
if (!StrEqual(sEntityClass, "instanced_scripted_scene"))
{
return;
}
SDKUnhook(entity, SDKHook_SpawnPost, OnSpawnPost);
SceneStages ssBit = nSceneData[entity][ssDataBit];
if (ssBit != SceneStage_Unknown)
{
if (ssBit == SceneStage_Started)
{
SceneData_SetStage(entity, SceneStage_Completion);
}
SceneData_SetStage(entity, SceneStage_Killed);
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientInGame(i) || iScenePlaying[i] != entity)
{
continue;
}
iScenePlaying[i] = INVALID_ENT_REFERENCE;
break;
}
}
SceneData_SetStage(entity, SceneStage_Unknown);
}
public void OnClientDisconnect(int client)
{
if (client == 0)
{
return;
}
iScenePlaying[client] = INVALID_ENT_REFERENCE;
}
public void OnGameFrame()
{
iSkippedFrames += 1;
if (iSkippedFrames < 3)
{
return;
}
iSkippedFrames = 1;
if (bScenesUnprocessed)
{
bScenesUnprocessed = false;
decl dScene;
while (!asScene.Empty)
{
PopStackCell(asScene, dScene);
if (dScene < 1 || dScene > 2048 || !IsValidEntity(dScene))
{
continue;
}
if (nSceneData[dScene][ssDataBit] != SceneStage_Spawned)
{
continue;
}
nSceneData[dScene][fPreDelayData] = GetEntPropFloat(dScene, Prop_Data, "m_flPreDelay");
nSceneData[dScene][bInFakePostSpawn] = false;
SceneData_SetStage(dScene, SceneStage_SpawnedPost);
}
}
if (bUnvocalizedCommands)
{
int iArraySize = alVocalize.Length,
iCurrentTick = GetGameTickCount();
char sVocalize[MAX_VOCALIZE_LENGTH];
float fPreDelay, fPitch;
decl client, dInitiator, dTick;
for (int i = 0; i < iArraySize; i += 6)
{
dTick = alVocalize.Get(i + 5);
if (iCurrentTick != dTick)
{
continue;
}
client = alVocalize.Get(i + 0);
alVocalize.GetString(i + 1, sVocalize, MAX_VOCALIZE_LENGTH);
fPreDelay = Float:alVocalize.Get(i + 2);
fPitch = Float:alVocalize.Get(i + 3);
dInitiator = alVocalize.Get(i + 4);
Scene_Perform(client, sVocalize, _, fPreDelay, fPitch, dInitiator, true);
for (int j = 0; j < 6; j++)
{
alVocalize.Erase(i);
iArraySize -= 1;
}
}
if (iArraySize < 1)
{
alVocalize.Clear();
bUnvocalizedCommands = false;
}
}
}
public void OnMapEnd()
{
iSkippedFrames = 0;
bScenesUnprocessed = false;
bUnvocalizedCommands = false;
while (!asScene.Empty)
{
PopStack(asScene);
}
alVocalize.Clear();
for (int i = 1; i < 2049; i++)
{
if (IsValidEntity(i) && IsValidEdict(i))
{
SceneData_SetStage(i, SceneStage_Unknown);
}
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
iScenePlaying[i] = INVALID_ENT_REFERENCE;
}
}
}
void ResetClientVocalizeData(int client)
{
iVocalizeTick[client] = 0;
sVocalizeScene[client] = "\0";
bSceneHasInitiator[client] = false;
iVocalizeInitiator[client] = SCENE_INITIATOR_WORLD;
fVocalizePreDelay[client] = DEFAULT_SCENE_PREDELAY;
fVocalizePitch[client] = DEFAULT_SCENE_PITCH;
}
void SceneData_SetStage(int scene, SceneStages stage)
{
nSceneData[scene][ssDataBit] = stage;
if (stage != SceneStage_Unknown)
{
Call_StartForward(hSceneStageForward);
Call_PushCell(scene);
Call_PushCell(stage);
Call_Finish();
}
else
{
nSceneData[scene][bInFakePostSpawn] = false;
nSceneData[scene][fTimeStampData] = 0.0;
nSceneData[scene][iActorData] = 0;
nSceneData[scene][iInitiatorData] = 0;
strcopy(nSceneData[scene][sFileData], MAX_SCENEFILE_LENGTH, "\0");
strcopy(nSceneData[scene][sVocalizeData], MAX_VOCALIZE_LENGTH, "\0");
nSceneData[scene][fPreDelayData] = DEFAULT_SCENE_PREDELAY;
nSceneData[scene][fPitchData] = DEFAULT_SCENE_PITCH;
}
}
void Scene_Perform(int client, const char[] sVocalizeParam, const char[] sFileParam = "", float fScenePreDelay = DEFAULT_SCENE_PREDELAY, float fScenePitch = DEFAULT_SCENE_PITCH, int iSceneInitiator = SCENE_INITIATOR_PLUGIN, bool bVocalizeNow = false)
{
if (strlen(sFileParam) > 0 && FileExists(sFileParam, true))
{
int iScene = CreateEntityByName("instanced_scripted_scene");
DispatchKeyValue(iScene, "SceneFile", sFileParam);
SetEntPropEnt(iScene, Prop_Data, "m_hOwner", client);
nSceneData[iScene][iActorData] = client;
SetEntPropFloat(iScene, Prop_Data, "m_flPreDelay", fScenePreDelay);
nSceneData[iScene][fPreDelayData] = fScenePreDelay;
SetEntPropFloat(iScene, Prop_Data, "m_fPitch", fScenePitch);
nSceneData[iScene][fPitchData] = fScenePitch;
nSceneData[iScene][iInitiatorData] = iSceneInitiator;
strcopy(nSceneData[iScene][sVocalizeData], MAX_VOCALIZE_LENGTH, sVocalizeParam);
DispatchSpawn(iScene);
ActivateEntity(iScene);
AcceptEntityInput(iScene, "Start", client, client);
}
else if (strlen(sVocalizeParam) > 0)
{
if (bVocalizeNow)
{
iVocalizeInitiator[client] = iSceneInitiator;
bSceneHasInitiator[client] = true;
fVocalizePreDelay[client] = fScenePreDelay;
fVocalizePitch[client] = fScenePitch;
if (bIsL4D)
{
FakeClientCommandEx(client, "vocalize %s", sVocalizeParam);
}
else
{
JailbreakVocalize(client, sVocalizeParam);
}
}
else
{
alVocalize.Push(client);
alVocalize.PushString(sVocalizeParam);
alVocalize.Push(fScenePreDelay);
alVocalize.Push(fScenePitch);
alVocalize.Push(iSceneInitiator);
alVocalize.Push(GetGameTickCount() + 10 - 1);
bUnvocalizedCommands = true;
}
}
}
void JailbreakVocalize(int client, const char[] sVocalize)
{
char sBuffer[2][32];
FloatToString((GetGameTime() - fStartTimeStamp) + 2.0, sBuffer[0], 32);
ExplodeString(sBuffer[0], ".", sBuffer, 2, 32);
Format(sBuffer[1], 2, "%s\0", sBuffer[1][0]);
FakeClientCommandEx(client, "vocalize %s #%s%s", sVocalize, sBuffer[0], sBuffer[1]);
}
sceneprocessor include
Spoiler
Code:
#if defined _sceneprocessor_included
#endinput
#endif
#define _sceneprocessor_included
#define MAX_SCENEFILE_LENGTH PLATFORM_MAX_PATH // Maximum length of scene files
#define MAX_VOCALIZE_LENGTH 128 // Maximum length of vocalize strings
#define SCENE_INITIATOR_WORLD 0 /* All scenes created by the map (such as landmarks, "Down this way", "Through here")
* and by the game (such as team mate actions, "Let me heal you up", "Help I'm falling")
* are marked as started by the world, or entity index 0. */
#define SCENE_INITIATOR_PLUGIN -1 /* All scenes started by the Scene Processor are by default marked as started by plugin or
* entity index -1. This can be changed in the PerformScene function call. */
#define DEFAULT_SCENE_PREDELAY 0.0 /* By default all scenes occur the instant they are created */
#define DEFAULT_SCENE_PITCH 1.0 /* By default all scenes have a pitch of 1.0, or as they are normally heard. 2.0 will make
* it sounds twice as fast but in a high pitched voice. 0.5 will be half the normal speed
* and with low pitched voice. */
enum SceneStages
{
SceneStage_Unknown = 0, /* Scene has not been created nor processed. Either something went wrong, the
* scene is not valid, incorrectly formatted, or a round just started recently. */
SceneStage_Created = 1, /* When scene is created. Contains no information about the scene that is about to
* be played out. Guaranteed to occur. */
SceneStage_Spawned, /* When scene is spawned. Everything is filled in but the pre-delay! Change scene
* pitch and pre-delay here. */
SceneStage_SpawnedPost, /* Post scene spawned frame. Pre-delay is now filled out. Pre-delay can be changed
* here if the scene originally has a pre-delay greater than 0.0. */
SceneStage_Started, /* When scene is started. Time stamp is set. */
SceneStage_Cancelled, /* When scene is cancelled. Happens if the Survivor was interrupted by another scene
* or the scene was cancelled post starting. */
SceneStage_Completion, /* When scene is completed. Happens if the Survivor gets to fully perform the scene
* with no interruptions or cancellation. Entity index is no longer valid but
* information is retained. */
SceneStage_Killed /* When scene is killed. Entity index is no longer valid but information is retained
* until end of forward. Guaranteed to occur */
};
/**
* Called on scene stage changed.
*
* @param scene Scene entity index.
* @param stage SceneStages value.
* @noreturn
*/
forward void OnSceneStageChanged(int scene, SceneStages stage);
/**
* Called on vocalize command send.
*
* @remarks See SCENE_INITIATOR_WORLD and SCENE_INITIATOR_PLUGIN for
* non-client initiated vocalizes.
*
* @param client Index of player sending vocalize command.
* @param vocalize String of what player wish to vocalize, as typed.
* @param initiator Index of entity initiated vocalize command.
* @return Plugin_Stop to stop vocalize command.
* Plugin_Continue to allow vocalize command.
*/
forward Action OnVocalizationProcess(int client, const char[] vocalize, int initiator);
/**
* Returns scene stage.
*
* @param scene Scene entity index.
* @return SceneStages value or 0 if scene is not valid.
*/
native SceneStages GetSceneStage(int scene);
/**
* Returns whether scene is valid as a scene.
*
* @remarks The scene entity index may still be invalid.
*
* @param scene Scene entity index.
* @return True if a valid scene, false otherwise.
*/
stock bool IsValidScene(int scene)
{
return GetSceneStage(scene) != view_as<SceneStages>(0);
}
/**
* Returns scene start time stamp, in engine time.
*
* @param scene Scene entity index.
* @return Scene start engine time stamp. 0.0 if the scene has not started yet.
*/
native float GetSceneStartTimeStamp(int scene);
/**
* Returns scene actor.
*
* @param scene Scene entity index.
* @return Actor of the scene. 0 if no one is playing it.
*/
native int GetActorFromScene(int scene);
/**
* Returns actor's scene.
*
* @remarks Only returns scene if it is currently being played out.
*
* @param actor Client index of actor.
* @return Scene entity index. INVALID_ENT_REFERENCE if actor currently aren't playing.
*/
native int GetSceneFromActor(int actor);
/**
* Returns whether actor is already playing a scene.
*
* @param actor Client index of actor.
* @return True if actor is busy, false otherwise.
*/
stock bool IsActorBusy(int actor)
{
return GetSceneFromActor(actor) != INVALID_ENT_REFERENCE;
}
/**
* Returns scene initiator.
*
* @remarks See SCENE_INITIATOR_WORLD and SCENE_INITIATOR_PLUGIN for automated
* scenes.
*
* @param scene Scene entity index.
* @return Initiator of the scene.
*/
native int GetSceneInitiator(int scene);
/**
* Returns scene file.
*
* @param scene Scene entity index.
* @param dest Destination string buffer to copy to.
* @param len Destination buffer length (includes null terminator).
* @return Number of bytes written
*/
native int GetSceneFile(int scene, char[] dest, int len);
/**
* Returns scene vocalize.
*
* @remarks Will only contain the vocalize string if the scene was started by
* the client them self. Otherwise empty.
*
* @param scene Scene entity index.
* @param dest Destination string buffer to copy to.
* @param len Destination buffer length (includes null terminator).
* @return Number of bytes written
*/
native int GetSceneVocalize(int scene, char[] dest, int len);
/**
* Returns scene pre-delay.
*
* @remarks Sadly pre-delay is first fetched on SceneStage_SpawnedPost where
* altering the pre-delay with SetScenePreDelay might already be too late.
*
* @param scene Scene entity index.
* @return Scene pre-delay in seconds.
*/
native float GetScenePreDelay(int scene);
/**
* Sets scene pre-delay.
*
* @remarks Pre-delay can be set on SceneStage_Spawned and sometimes (!) on
* SceneStage_SpawnedPost depending on whether the scene originally has a
* pre-delay. Once SceneStage_Started fires pre-delay is no longer obeyed.
*
* @param scene Scene entity index.
* @param preDelay Scene pre-delay in seconds.
* @noreturn
*/
native void SetScenePreDelay(int scene, float preDelay);
/**
* Returns scene pitch.
*
* @param scene Scene entity index.
* @return Scene pitch.
*/
native float GetScenePitch(int scene);
/**
* Sets scene pitch
*
* @remarks Scene pitch can be set on SceneStage_Spawned and
* SceneStage_SpawnedPost. Setting pitch post spawning results in weird
* settings such as some clients hearing 1.13 as double as fast instead of 2.0.
*
* @param scene Scene entity index.
* @param pitch Scene pitch.
* @noreturn
*/
native void SetScenePitch(int scene, float pitch);
/**
* Cancels scene.
*
* @remarks Can be used at all scene stages. Scene is validated before sending
* the cancel input.
*
* @param scene Scene entity index.
* @noreturn
*/
native void CancelScene(int scene);
/**
* Performs a scene.
*
* @remarks Scene file is used before vocalize string however vocalize string
* is still saved to scene entity index and can be retrieved for later usage.
* If vocalize string is used, it is delayed for a short while in order to
* work if used inside of OnSceneStageChanged. See PerformSceneEx to avoid
* this delay.
*
* @param client Client index.
* @param vocalize Vocalize string.
* @param file Scene file.
* @param preDelay Scene pre-delay.
* @param pitch Scene pitch.
* @param initiator Initiator of the scene.
* @noreturn
*/
native void PerformScene(int client, const char[] vocalize, const char[] file = "", float preDelay = DEFAULT_SCENE_PREDELAY, float pitch = DEFAULT_SCENE_PITCH, int initiator = SCENE_INITIATOR_PLUGIN);
/**
* Performs a scene.
*
* @remarks Works the same way as PerformScene however there is no delay when
* using vocalize string. Not recommend to use inside OnSceneStageChanged if
* vocalizes needs to get through.
*
* @param client Client index.
* @param vocalize Vocalize string.
* @param file Scene file.
* @param preDelay Scene pre-delay.
* @param pitch Scene pitch.
* @param initiator Initiator of the scene.
* @noreturn
*/
native void PerformSceneEx(int client, const char[] vocalize, const char[] file = "", float preDelay = DEFAULT_SCENE_PREDELAY, float pitch = DEFAULT_SCENE_PITCH, int initiator = SCENE_INITIATOR_PLUGIN);
public SharedPlugin __pl_sceneproces =
{
name = "sceneprocessor",
file = "sceneprocessor.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_sceneproces_SetNTVOptional()
{
MarkNativeAsOptional("GetSceneStage");
MarkNativeAsOptional("GetSceneStartTimeStamp");
MarkNativeAsOptional("GetActorFromScene");
MarkNativeAsOptional("GetSceneFromActor");
MarkNativeAsOptional("GetSceneInitiator");
MarkNativeAsOptional("GetSceneFile");
MarkNativeAsOptional("GetSceneVocalize");
MarkNativeAsOptional("GetScenePreDelay");
MarkNativeAsOptional("SetScenePreDelay");
MarkNativeAsOptional("GetScenePitch");
MarkNativeAsOptional("SetScenePitch");
MarkNativeAsOptional("CancelScene");
MarkNativeAsOptional("PerformScene");
MarkNativeAsOptional("PerformSceneEx");
}
#endif
The sound precache limit is like 20k, usually 12k~ is precached by game anyway
distorting sounds can you show video?
unless you have another plugin or something hooking sounds and changing attributes or you have some addon clientside/broken game.