quake4-sdk/source/game/script/Script_Thread.cpp
2007-06-15 00:00:00 +00:00

2309 lines
55 KiB
C++

#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
const idEventDef EV_Thread_Execute( "<execute>", NULL );
const idEventDef EV_Thread_SetCallback( "<script_setcallback>", NULL );
// script callable events
const idEventDef EV_Thread_TerminateThread( "terminate", "d" );
const idEventDef EV_Thread_Pause( "pause", NULL );
const idEventDef EV_Thread_Wait( "wait", "f" );
const idEventDef EV_Thread_WaitFrame( "waitFrame" );
const idEventDef EV_Thread_WaitFor( "waitFor", "e" );
const idEventDef EV_Thread_WaitForThread( "waitForThread", "d" );
const idEventDef EV_Thread_Print( "print", "s" );
const idEventDef EV_Thread_PrintLn( "println", "s" );
const idEventDef EV_Thread_Say( "say", "s" );
const idEventDef EV_Thread_Assert( "assert", "f" );
const idEventDef EV_Thread_Trigger( "trigger", "e" );
const idEventDef EV_Thread_SetCvar( "setcvar", "ss" );
const idEventDef EV_Thread_GetCvar( "getcvar", "s", 's' );
const idEventDef EV_Thread_Random( "random", "f", 'f' );
const idEventDef EV_Thread_GetTime( "getTime", NULL, 'f' );
const idEventDef EV_Thread_KillThread( "killthread", "s" );
const idEventDef EV_Thread_SetThreadName( "threadname", "s" );
const idEventDef EV_Thread_GetEntity( "getEntity", "s", 'e' );
const idEventDef EV_Thread_Spawn( "spawn", "s", 'e' );
const idEventDef EV_Thread_CopySpawnArgs( "copySpawnArgs", "e" );
const idEventDef EV_Thread_SetSpawnArg( "setSpawnArg", "ss" );
const idEventDef EV_Thread_SpawnString( "SpawnString", "ss", 's' );
const idEventDef EV_Thread_SpawnFloat( "SpawnFloat", "sf", 'f' );
const idEventDef EV_Thread_SpawnVector( "SpawnVector", "sv", 'v' );
const idEventDef EV_Thread_ClearPersistantArgs( "clearPersistantArgs" );
const idEventDef EV_Thread_SetPersistantArg( "setPersistantArg", "ss" );
const idEventDef EV_Thread_GetPersistantString( "getPersistantString", "s", 's' );
const idEventDef EV_Thread_GetPersistantFloat( "getPersistantFloat", "s", 'f' );
const idEventDef EV_Thread_GetPersistantVector( "getPersistantVector", "s", 'v' );
const idEventDef EV_Thread_AngToForward( "angToForward", "v", 'v' );
const idEventDef EV_Thread_AngToRight( "angToRight", "v", 'v' );
const idEventDef EV_Thread_AngToUp( "angToUp", "v", 'v' );
const idEventDef EV_Thread_Sine( "sin", "f", 'f' );
const idEventDef EV_Thread_Cosine( "cos", "f", 'f' );
const idEventDef EV_Thread_SquareRoot( "sqrt", "f", 'f' );
const idEventDef EV_Thread_Normalize( "vecNormalize", "v", 'v' );
const idEventDef EV_Thread_VecLength( "vecLength", "v", 'f' );
const idEventDef EV_Thread_VecDotProduct( "DotProduct", "vv", 'f' );
const idEventDef EV_Thread_VecCrossProduct( "CrossProduct", "vv", 'v' );
const idEventDef EV_Thread_VecToAngles( "VecToAngles", "v", 'v' );
const idEventDef EV_Thread_OnSignal( "onSignal", "des" );
const idEventDef EV_Thread_ClearSignal( "clearSignalThread", "de" );
const idEventDef EV_Thread_SetCamera( "setCamera", "e" );
const idEventDef EV_Thread_FirstPerson( "firstPerson", NULL );
const idEventDef EV_Thread_Trace( "trace", "vvvvde", 'f' );
const idEventDef EV_Thread_TracePoint( "tracePoint", "vvde", 'f' );
const idEventDef EV_Thread_GetTraceFraction( "getTraceFraction", NULL, 'f' );
const idEventDef EV_Thread_GetTraceEndPos( "getTraceEndPos", NULL, 'v' );
const idEventDef EV_Thread_GetTraceNormal( "getTraceNormal", NULL, 'v' );
const idEventDef EV_Thread_GetTraceEntity( "getTraceEntity", NULL, 'e' );
const idEventDef EV_Thread_GetTraceJoint( "getTraceJoint", NULL, 's' );
const idEventDef EV_Thread_GetTraceBody( "getTraceBody", NULL, 's' );
const idEventDef EV_Thread_FadeIn( "fadeIn", "vf" );
const idEventDef EV_Thread_FadeOut( "fadeOut", "vf" );
const idEventDef EV_Thread_FadeTo( "fadeTo", "vff" );
const idEventDef EV_Thread_StartMusic( "music", "s" );
const idEventDef EV_Thread_Error( "error", "s" );
const idEventDef EV_Thread_Warning( "warning", "s" );
const idEventDef EV_Thread_StrLen( "strLength", "s", 'd' );
const idEventDef EV_Thread_StrLeft( "strLeft", "sd", 's' );
const idEventDef EV_Thread_StrRight( "strRight", "sd", 's' );
const idEventDef EV_Thread_StrSkip( "strSkip", "sd", 's' );
const idEventDef EV_Thread_StrMid( "strMid", "sdd", 's' );
const idEventDef EV_Thread_StrToFloat( "strToFloat", "s", 'f' );
const idEventDef EV_Thread_RadiusDamage( "radiusDamage", "vEEEsf" );
const idEventDef EV_Thread_IsClient( "isClient", NULL, 'f' );
const idEventDef EV_Thread_IsMultiplayer( "isMultiplayer", NULL, 'f' );
const idEventDef EV_Thread_GetFrameTime( "getFrameTime", NULL, 'f' );
const idEventDef EV_Thread_GetTicsPerSecond( "getTicsPerSecond", NULL, 'f' );
const idEventDef EV_Thread_DebugLine( "debugLine", "vvvf" );
const idEventDef EV_Thread_DebugArrow( "debugArrow", "vvvdf" );
const idEventDef EV_Thread_DebugCircle( "debugCircle", "vvvfdf" );
const idEventDef EV_Thread_DebugBounds( "debugBounds", "vvvf" );
const idEventDef EV_Thread_DrawText( "drawText", "svfvdf" );
const idEventDef EV_Thread_InfluenceActive( "influenceActive", NULL, 'd' );
// RAVEN BEGIN
// kfuller: added everything below the above block
const idEventDef EV_Thread_SetSpawnVector( "setSpawnVector", "sv" );
const idEventDef EV_Thread_ArcSine( "asin", "f", 'f' );
const idEventDef EV_Thread_ArcCosine( "acos", "f", 'f' );
const idEventDef EV_Thread_VecRotate( "vecRotate", "vv", 'v');
const idEventDef EV_Thread_ClearSignalAllThreads( "clearSignalAllThreads", "de" );
// bgeisler: added everything below the added block that was added by keith
const idEventDef EV_Thread_PlayWorldEffect( "playWorldEffect", "svv");
// abahr:
const idEventDef EV_Thread_ReferenceScriptObjectProxy( "refProxy", "s", 'e' );
const idEventDef EV_Thread_ReleaseScriptObjectProxy( "releaseProxy", "s" );
const idEventDef EV_Thread_ClampFloat( "clampFloat", "fff", 'f' );
const idEventDef EV_Thread_MinFloat( "minFloat", "ff", 'f' );
const idEventDef EV_Thread_MaxFloat( "maxFloat", "ff", 'f' );
const idEventDef EV_Thread_StrFind( "strFind", "ss", 'f' );
const idEventDef EV_Thread_RandomInt( "randomInt", "f", 'f' );
// rjohnson: new blur special effect
const idEventDef EV_Thread_SetSpecialEffect( "setSpecialEffect", "dd" );
const idEventDef EV_Thread_SetSpecialEffectParm( "setSpecialEffectParm", "ddf" );
// asalmon: award achievement
const idEventDef EV_Thread_AwardAchievement( "awardAchievement", "s" );
// twhitaker: ceil, floor and intVal
const idEventDef EV_Thread_Ceil( "ceil", "f", 'f' );
const idEventDef EV_Thread_Floor( "floor", "f", 'f' );
const idEventDef EV_Thread_ToInt( "intVal", "f", 'f' );
// jdischler: send named event string to specified gui
const idEventDef EV_Thread_SendNamedEvent( "sendNamedEvent", "ds" );
// material streaming
const idEventDef EV_Thread_BeginManualStreaming( "beginManualStreaming" );
const idEventDef EV_Thread_EndManualStreaming( "endManualStreaming" );
// nrausch: change material sort order on the fly
const idEventDef EV_Thread_SetMatSort( "setMatSort", "ss", 0 );
// RAVEN END
CLASS_DECLARATION( idClass, idThread )
EVENT( EV_Thread_Execute, idThread::Event_Execute )
EVENT( EV_Thread_TerminateThread, idThread::Event_TerminateThread )
EVENT( EV_Thread_Pause, idThread::Event_Pause )
EVENT( EV_Thread_Wait, idThread::Event_Wait )
EVENT( EV_Thread_WaitFrame, idThread::Event_WaitFrame )
EVENT( EV_Thread_WaitFor, idThread::Event_WaitFor )
EVENT( EV_Thread_WaitForThread, idThread::Event_WaitForThread )
EVENT( EV_Thread_Print, idThread::Event_Print )
EVENT( EV_Thread_PrintLn, idThread::Event_PrintLn )
EVENT( EV_Thread_Say, idThread::Event_Say )
EVENT( EV_Thread_Assert, idThread::Event_Assert )
EVENT( EV_Thread_Trigger, idThread::Event_Trigger )
EVENT( EV_Thread_SetCvar, idThread::Event_SetCvar )
EVENT( EV_Thread_GetCvar, idThread::Event_GetCvar )
EVENT( EV_Thread_Random, idThread::Event_Random )
EVENT( EV_Thread_GetTime, idThread::Event_GetTime )
EVENT( EV_Thread_KillThread, idThread::Event_KillThread )
EVENT( EV_Thread_SetThreadName, idThread::Event_SetThreadName )
EVENT( EV_Thread_GetEntity, idThread::Event_GetEntity )
EVENT( EV_Thread_Spawn, idThread::Event_Spawn )
EVENT( EV_Thread_CopySpawnArgs, idThread::Event_CopySpawnArgs )
EVENT( EV_Thread_SetSpawnArg, idThread::Event_SetSpawnArg )
EVENT( EV_Thread_SpawnString, idThread::Event_SpawnString )
EVENT( EV_Thread_SpawnFloat, idThread::Event_SpawnFloat )
EVENT( EV_Thread_SpawnVector, idThread::Event_SpawnVector )
EVENT( EV_Thread_ClearPersistantArgs, idThread::Event_ClearPersistantArgs )
EVENT( EV_Thread_SetPersistantArg, idThread::Event_SetPersistantArg )
EVENT( EV_Thread_GetPersistantString, idThread::Event_GetPersistantString )
EVENT( EV_Thread_GetPersistantFloat, idThread::Event_GetPersistantFloat )
EVENT( EV_Thread_GetPersistantVector, idThread::Event_GetPersistantVector )
EVENT( EV_Thread_AngToForward, idThread::Event_AngToForward )
EVENT( EV_Thread_AngToRight, idThread::Event_AngToRight )
EVENT( EV_Thread_AngToUp, idThread::Event_AngToUp )
EVENT( EV_Thread_Sine, idThread::Event_GetSine )
EVENT( EV_Thread_Cosine, idThread::Event_GetCosine )
EVENT( EV_Thread_SquareRoot, idThread::Event_GetSquareRoot )
EVENT( EV_Thread_Normalize, idThread::Event_VecNormalize )
EVENT( EV_Thread_VecLength, idThread::Event_VecLength )
EVENT( EV_Thread_VecDotProduct, idThread::Event_VecDotProduct )
EVENT( EV_Thread_VecCrossProduct, idThread::Event_VecCrossProduct )
EVENT( EV_Thread_VecToAngles, idThread::Event_VecToAngles )
EVENT( EV_Thread_OnSignal, idThread::Event_OnSignal )
EVENT( EV_Thread_ClearSignal, idThread::Event_ClearSignalThread )
EVENT( EV_Thread_SetCamera, idThread::Event_SetCamera )
EVENT( EV_Thread_FirstPerson, idThread::Event_FirstPerson )
EVENT( EV_Thread_Trace, idThread::Event_Trace )
EVENT( EV_Thread_TracePoint, idThread::Event_TracePoint )
EVENT( EV_Thread_GetTraceFraction, idThread::Event_GetTraceFraction )
EVENT( EV_Thread_GetTraceEndPos, idThread::Event_GetTraceEndPos )
EVENT( EV_Thread_GetTraceNormal, idThread::Event_GetTraceNormal )
EVENT( EV_Thread_GetTraceEntity, idThread::Event_GetTraceEntity )
EVENT( EV_Thread_GetTraceJoint, idThread::Event_GetTraceJoint )
EVENT( EV_Thread_GetTraceBody, idThread::Event_GetTraceBody )
EVENT( EV_Thread_FadeIn, idThread::Event_FadeIn )
EVENT( EV_Thread_FadeOut, idThread::Event_FadeOut )
EVENT( EV_Thread_FadeTo, idThread::Event_FadeTo )
EVENT( EV_SetShaderParm, idThread::Event_SetShaderParm )
EVENT( EV_Thread_StartMusic, idThread::Event_StartMusic )
EVENT( EV_Thread_Warning, idThread::Event_Warning )
EVENT( EV_Thread_Error, idThread::Event_Error )
EVENT( EV_Thread_StrLen, idThread::Event_StrLen )
EVENT( EV_Thread_StrLeft, idThread::Event_StrLeft )
EVENT( EV_Thread_StrRight, idThread::Event_StrRight )
EVENT( EV_Thread_StrSkip, idThread::Event_StrSkip )
EVENT( EV_Thread_StrMid, idThread::Event_StrMid )
EVENT( EV_Thread_StrToFloat, idThread::Event_StrToFloat )
EVENT( EV_Thread_RadiusDamage, idThread::Event_RadiusDamage )
EVENT( EV_Thread_IsClient, idThread::Event_IsClient )
EVENT( EV_Thread_IsMultiplayer, idThread::Event_IsMultiplayer )
EVENT( EV_Thread_GetFrameTime, idThread::Event_GetFrameTime )
EVENT( EV_Thread_GetTicsPerSecond, idThread::Event_GetTicsPerSecond )
EVENT( EV_CacheSoundShader, idThread::Event_CacheSoundShader )
EVENT( EV_Thread_DebugLine, idThread::Event_DebugLine )
EVENT( EV_Thread_DebugArrow, idThread::Event_DebugArrow )
EVENT( EV_Thread_DebugCircle, idThread::Event_DebugCircle )
EVENT( EV_Thread_DebugBounds, idThread::Event_DebugBounds )
EVENT( EV_Thread_DrawText, idThread::Event_DrawText )
EVENT( EV_Thread_InfluenceActive, idThread::Event_InfluenceActive )
// RAVEN BEGIN
// kfuller: added events
EVENT( EV_Thread_SetSpawnVector, idThread::Event_SetSpawnVector )
EVENT( EV_Thread_ArcSine, idThread::Event_GetArcSine )
EVENT( EV_Thread_ArcCosine, idThread::Event_GetArcCosine )
EVENT( EV_Thread_VecRotate, idThread::Event_VecRotate )
EVENT( EV_Thread_ClearSignalAllThreads, idThread::Event_ClearSignalAllThreads )
// nmckenzie: added signal strings
EVENT( EV_Thread_PlayWorldEffect, idThread::Event_PlayWorldEffect )
// abahr:
EVENT( EV_Thread_ReferenceScriptObjectProxy, idThread::Event_ReferenceScriptObjectProxy )
EVENT( EV_Thread_ReleaseScriptObjectProxy, idThread::Event_ReleaseScriptObjectProxy )
EVENT( EV_Thread_ClampFloat, idThread::Event_ClampFloat )
EVENT( EV_Thread_MinFloat, idThread::Event_MinFloat )
EVENT( EV_Thread_MaxFloat, idThread::Event_MaxFloat )
EVENT( EV_Thread_StrFind, idThread::Event_StrFind )
EVENT( EV_Thread_RandomInt, idThread::Event_RandomInt )
// rjohnson: new blur special effect
EVENT( EV_Thread_SetSpecialEffect, idThread::Event_SetSpecialEffect )
EVENT( EV_Thread_SetSpecialEffectParm, idThread::Event_SetSpecialEffectParm )
// asalmon: award a Xenon achievement
EVENT( EV_Thread_AwardAchievement, idThread::Event_AwardAchievement )
// twhitaker: ceil and floor
EVENT( EV_Thread_Ceil, idThread::Event_GetCeil )
EVENT( EV_Thread_Floor, idThread::Event_GetFloor )
EVENT( EV_Thread_ToInt, idThread::Event_ToInt )
// jdischler: send named event string to specified gui
EVENT( EV_Thread_SendNamedEvent, idThread::Event_SendNamedEvent )
// manual streaming
EVENT( EV_Thread_BeginManualStreaming, idThread::Event_BeginManualStreaming )
EVENT( EV_Thread_EndManualStreaming, idThread::Event_EndManualStreaming )
EVENT( EV_Thread_SetMatSort, idThread::Event_SetMatSort )
// RAVEN END
END_CLASS
idThread *idThread::currentThread = NULL;
int idThread::threadIndex = 0;
idList<idThread *> idThread::threadList;
trace_t idThread::trace;
/*
================
idThread::CurrentThread
================
*/
idThread *idThread::CurrentThread( void ) {
return currentThread;
}
/*
================
idThread::CurrentThreadNum
================
*/
int idThread::CurrentThreadNum( void ) {
if ( currentThread ) {
return currentThread->GetThreadNum();
} else {
return 0;
}
}
/*
================
idThread::BeginMultiFrameEvent
================
*/
bool idThread::BeginMultiFrameEvent( idEntity *ent, const idEventDef *event ) {
if ( !currentThread ) {
gameLocal.Error( "idThread::BeginMultiFrameEvent called without a current thread" );
}
return currentThread->interpreter.BeginMultiFrameEvent( ent, event );
}
/*
================
idThread::EndMultiFrameEvent
================
*/
void idThread::EndMultiFrameEvent( idEntity *ent, const idEventDef *event ) {
if ( !currentThread ) {
gameLocal.Error( "idThread::EndMultiFrameEvent called without a current thread" );
}
currentThread->interpreter.EndMultiFrameEvent( ent, event );
}
/*
================
idThread::idThread
================
*/
idThread::idThread() {
Init();
SetThreadName( va( "thread_%d", threadIndex ) );
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: create thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
}
/*
================
idThread::idThread
================
*/
idThread::idThread( idEntity *self, const function_t *func ) {
assert( self );
Init();
SetThreadName( self->name );
interpreter.EnterObjectFunction( self, func, false );
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: create thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
}
/*
================
idThread::idThread
================
*/
idThread::idThread( const function_t *func ) {
assert( func );
Init();
SetThreadName( func->Name() );
interpreter.EnterFunction( func, false );
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: create thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
}
/*
================
idThread::idThread
================
*/
idThread::idThread( idInterpreter *source, const function_t *func, int args ) {
Init();
interpreter.ThreadCall( source, func, args );
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: create thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
}
/*
================
idThread::idThread
================
*/
idThread::idThread( idInterpreter *source, idEntity *self, const function_t *func, int args ) {
assert( self );
Init();
SetThreadName( self->name );
interpreter.ThreadCall( source, func, args );
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: create thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
}
/*
================
idThread::~idThread
================
*/
idThread::~idThread() {
idThread *thread;
int i;
int n;
if ( g_debugScript.GetBool() ) {
gameLocal.Printf( "%d: end thread (%d) '%s'\n", gameLocal.time, threadNum, threadName.c_str() );
}
threadList.Remove( this );
n = threadList.Num();
for( i = 0; i < n; i++ ) {
thread = threadList[ i ];
if ( thread->WaitingOnThread() == this ) {
thread->ThreadCallback( this );
}
}
if ( currentThread == this ) {
currentThread = NULL;
}
}
/*
================
idThread::ManualDelete
================
*/
void idThread::ManualDelete( void ) {
interpreter.terminateOnExit = false;
}
/*
================
idThread::Save
================
*/
void idThread::Save( idSaveGame *savefile ) const {
savefile->WriteObject( currentThread );
savefile->WriteObject( waitingForThread );
savefile->WriteInt( waitingFor );
savefile->WriteInt( waitingUntil );
interpreter.Save( savefile );
savefile->WriteDict( &spawnArgs );
savefile->WriteInt( threadNum );
savefile->WriteString( threadName );
savefile->WriteInt( lastExecuteTime );
savefile->WriteInt( creationTime );
savefile->WriteBool( manualControl );
savefile->WriteInt( threadIndex );
}
/*
================
idThread::Restore
================
*/
void idThread::Restore( idRestoreGame *savefile ) {
savefile->ReadObject( reinterpret_cast<idClass *&>( currentThread ) );
savefile->ReadObject( reinterpret_cast<idClass *&>( waitingForThread ) );
savefile->ReadInt( waitingFor );
savefile->ReadInt( waitingUntil );
interpreter.Restore( savefile );
savefile->ReadDict( &spawnArgs );
savefile->ReadInt( threadNum );
savefile->ReadString( threadName );
savefile->ReadInt( lastExecuteTime );
savefile->ReadInt( creationTime );
savefile->ReadBool( manualControl );
savefile->ReadInt( threadIndex );
}
/*
================
idThread::Init
================
*/
void idThread::Init( void ) {
// create a unique threadNum
do {
threadIndex++;
if ( threadIndex == 0 ) {
threadIndex = 1;
}
} while( GetThread( threadIndex ) );
threadNum = threadIndex;
threadList.Append( this );
creationTime = gameLocal.time;
lastExecuteTime = 0;
manualControl = false;
ClearWaitFor();
interpreter.SetThread( this );
}
/*
================
idThread::GetThread
================
*/
idThread *idThread::GetThread( int num ) {
int i;
int n;
idThread *thread;
n = threadList.Num();
for( i = 0; i < n; i++ ) {
thread = threadList[ i ];
if ( thread->GetThreadNum() == num ) {
return thread;
}
}
return NULL;
}
/*
================
idThread::DisplayInfo
================
*/
void idThread::DisplayInfo( void ) {
gameLocal.Printf(
"%12i: '%s'\n"
" File: %s(%d)\n"
" Created: %d (%d ms ago)\n"
" Status: ",
threadNum, threadName.c_str(),
interpreter.CurrentFile(), interpreter.CurrentLine(),
creationTime, gameLocal.time - creationTime );
if ( interpreter.threadDying ) {
gameLocal.Printf( "Dying\n" );
} else if ( interpreter.doneProcessing ) {
gameLocal.Printf(
"Paused since %d (%d ms)\n"
" Reason: ", lastExecuteTime, gameLocal.time - lastExecuteTime );
if ( waitingForThread ) {
gameLocal.Printf( "Waiting for thread #%3i '%s'\n", waitingForThread->GetThreadNum(), waitingForThread->GetThreadName() );
} else if ( ( waitingFor != ENTITYNUM_NONE ) && ( gameLocal.entities[ waitingFor ] ) ) {
gameLocal.Printf( "Waiting for entity #%3i '%s'\n", waitingFor, gameLocal.entities[ waitingFor ]->name.c_str() );
} else if ( waitingUntil ) {
gameLocal.Printf( "Waiting until %d (%d ms total wait time)\n", waitingUntil, waitingUntil - lastExecuteTime );
} else {
gameLocal.Printf( "None\n" );
}
} else {
gameLocal.Printf( "Processing\n" );
}
interpreter.DisplayInfo();
gameLocal.Printf( "\n" );
}
/*
================
idThread::ListThreads_f
================
*/
void idThread::ListThreads_f( const idCmdArgs &args ) {
int i;
int n;
n = threadList.Num();
for( i = 0; i < n; i++ ) {
//threadList[ i ]->DisplayInfo();
gameLocal.Printf( "%3i: %-20s : %s(%d)\n", threadList[ i ]->threadNum, threadList[ i ]->threadName.c_str(), threadList[ i ]->interpreter.CurrentFile(), threadList[ i ]->interpreter.CurrentLine() );
}
gameLocal.Printf( "%d active threads\n\n", n );
}
/*
================
idThread::Restart
================
*/
void idThread::Restart( void ) {
int i;
int n;
// reset the threadIndex
threadIndex = 0;
currentThread = NULL;
n = threadList.Num();
for( i = n - 1; i >= 0; i-- ) {
delete threadList[ i ];
}
threadList.Clear();
memset( &trace, 0, sizeof( trace ) );
trace.c.entityNum = ENTITYNUM_NONE;
}
/*
================
idThread::DelayedStart
================
*/
void idThread::DelayedStart( int delay ) {
CancelEvents( &EV_Thread_Execute );
if ( gameLocal.time <= 0 ) {
delay++;
}
PostEventMS( &EV_Thread_Execute, delay );
}
/*
================
idThread::Start
================
*/
bool idThread::Start( void ) {
bool result;
CancelEvents( &EV_Thread_Execute );
result = Execute();
return result;
}
/*
================
idThread::SetThreadName
================
*/
void idThread::SetThreadName( const char *name ) {
threadName = name;
}
/*
================
idThread::ObjectMoveDone
================
*/
void idThread::ObjectMoveDone( int threadnum, idEntity *obj ) {
idThread *thread;
if ( !threadnum ) {
return;
}
thread = GetThread( threadnum );
if ( thread ) {
thread->ObjectMoveDone( obj );
}
}
/*
================
idThread::End
================
*/
void idThread::End( void ) {
// Tell thread to die. It will exit on its own.
Pause();
interpreter.threadDying = true;
}
/*
================
idThread::KillThread
================
*/
void idThread::KillThread( const char *name ) {
int i;
int num;
int len;
const char *ptr;
idThread *thread;
// see if the name uses a wild card
ptr = strchr( name, '*' );
if ( ptr ) {
len = ptr - name;
} else {
len = strlen( name );
}
// kill only those threads whose name matches name
num = threadList.Num();
for( i = 0; i < num; i++ ) {
thread = threadList[ i ];
if ( !idStr::Cmpn( thread->GetThreadName(), name, len ) ) {
thread->End();
}
}
}
/*
================
idThread::KillThread
================
*/
void idThread::KillThread( int num ) {
idThread *thread;
thread = GetThread( num );
if ( thread ) {
// Tell thread to die. It will delete itself on it's own.
thread->End();
}
}
/*
================
idThread::Execute
================
*/
bool idThread::Execute( void ) {
idThread *oldThread;
bool done;
if ( manualControl && ( waitingUntil > gameLocal.time ) ) {
return false;
}
oldThread = currentThread;
currentThread = this;
lastExecuteTime = gameLocal.time;
ClearWaitFor();
done = interpreter.Execute();
if ( done ) {
End();
if ( interpreter.terminateOnExit ) {
PostEventMS( &EV_Remove, 0 );
}
} else if ( !manualControl ) {
if ( waitingUntil > lastExecuteTime ) {
PostEventMS( &EV_Thread_Execute, waitingUntil - lastExecuteTime );
} else if ( interpreter.MultiFrameEventInProgress() ) {
PostEventMS( &EV_Thread_Execute, gameLocal.msec );
}
}
currentThread = oldThread;
return done;
}
/*
================
idThread::IsWaiting
Checks if thread is still waiting for some event to occur.
================
*/
bool idThread::IsWaiting( void ) {
if ( waitingForThread || ( waitingFor != ENTITYNUM_NONE ) ) {
return true;
}
if ( waitingUntil && ( waitingUntil > gameLocal.time ) ) {
return true;
}
return false;
}
// RAVEN BEGIN
// bgeisler:
/*
================
idThread::ListFunctions
================
*/
void idThread::ListStates(void)
{
gameLocal.program.ListStates();
}
// abahr: added helper functions
/*
================
idThread::ClearStack
================
*/
void idThread::ClearStack() {
interpreter.Reset();
}
/*
================
idThread::PushInt
================
*/
void idThread::PushInt( int value ) {
interpreter.Push( value );
}
/*
================
idThread::PushFloat
================
*/
void idThread::PushFloat( float value ) {
interpreter.Push( *(int*)&value );
}
/*
================
idThread::PushVec3
================
*/
void idThread::PushVec3( const idVec3& value ) {
for( int ix = 0; ix < value.GetDimension(); ++ix ) {
PushFloat( value[ix] );
}
}
/*
================
idThread::PushEntity
================
*/
void idThread::PushEntity( const idEntity* ent ) {
assert( ent );
PushInt( ent->entityNumber + 1 );
}
/*
================
idThread::PushString
================
*/
void idThread::PushString( const char* string ) {
interpreter.PushString( string );
}
/*
================
idThread::PushBool
================
*/
void idThread::PushBool( bool value ) {
PushInt( (int)value );
}
// RAVEN END
/*
================
idThread::CallFunction
NOTE: If this is called from within a event called by this thread, the function arguments will be invalid after calling this function.
================
*/
void idThread::CallFunction( const function_t *func, bool clearStack ) {
ClearWaitFor();
interpreter.EnterFunction( func, clearStack );
}
/*
================
idThread::CallFunction
NOTE: If this is called from within a event called by this thread, the function arguments will be invalid after calling this function.
================
*/
void idThread::CallFunction( idEntity *self, const function_t *func, bool clearStack ) {
assert( self );
ClearWaitFor();
interpreter.EnterObjectFunction( self, func, clearStack );
}
/*
================
idThread::ClearWaitFor
================
*/
void idThread::ClearWaitFor( void ) {
waitingFor = ENTITYNUM_NONE;
waitingForThread = NULL;
waitingUntil = 0;
}
/*
================
idThread::IsWaitingFor
================
*/
bool idThread::IsWaitingFor( idEntity *obj ) {
assert( obj );
return waitingFor == obj->entityNumber;
}
/*
================
idThread::ObjectMoveDone
================
*/
void idThread::ObjectMoveDone( idEntity *obj ) {
assert( obj );
if ( IsWaitingFor( obj ) ) {
ClearWaitFor();
DelayedStart( 0 );
}
}
/*
================
idThread::ThreadCallback
================
*/
void idThread::ThreadCallback( idThread *thread ) {
if ( interpreter.threadDying ) {
return;
}
if ( thread == waitingForThread ) {
ClearWaitFor();
DelayedStart( 0 );
}
}
/*
================
idThread::Event_SetThreadName
================
*/
void idThread::Event_SetThreadName( const char *name ) {
SetThreadName( name );
}
/*
================
idThread::Error
================
*/
void idThread::Error( const char *fmt, ... ) const {
va_list argptr;
char text[ 1024 ];
va_start( argptr, fmt );
vsprintf( text, fmt, argptr );
va_end( argptr );
interpreter.Error( text );
}
/*
================
idThread::Warning
================
*/
void idThread::Warning( const char *fmt, ... ) const {
va_list argptr;
char text[ 1024 ];
va_start( argptr, fmt );
vsprintf( text, fmt, argptr );
va_end( argptr );
interpreter.Warning( text );
}
/*
================
idThread::ReturnString
================
*/
void idThread::ReturnString( const char *text ) {
gameLocal.program.ReturnString( text );
}
/*
================
idThread::ReturnFloat
================
*/
void idThread::ReturnFloat( float value ) {
gameLocal.program.ReturnFloat( value );
}
/*
================
idThread::ReturnInt
================
*/
void idThread::ReturnInt( int value ) {
// true integers aren't supported in the compiler,
// so int values are stored as floats
gameLocal.program.ReturnFloat( value );
}
/*
================
idThread::ReturnVector
================
*/
void idThread::ReturnVector( idVec3 const &vec ) {
gameLocal.program.ReturnVector( vec );
}
/*
================
idThread::ReturnEntity
================
*/
// RAVEN BEGIN
// abahr: added const
void idThread::ReturnEntity( const idEntity *ent ) {
gameLocal.program.ReturnEntity( ent );
}
/*
================
idThread::Event_Execute
================
*/
void idThread::Event_Execute( void ) {
Execute();
}
/*
================
idThread::Pause
================
*/
void idThread::Pause( void ) {
ClearWaitFor();
interpreter.doneProcessing = true;
}
/*
================
idThread::WaitMS
================
*/
void idThread::WaitMS( int time ) {
Pause();
// RAVEN BEGIN
// bdube: add 1 ms to ensure a time of zero still works
waitingUntil = gameLocal.time + time + 1;
// RAVEN END
}
/*
================
idThread::WaitSec
================
*/
void idThread::WaitSec( float time ) {
WaitMS( SEC2MS( time ) );
}
/*
================
idThread::WaitFrame
================
*/
void idThread::WaitFrame( void ) {
Pause();
// manual control threads don't set waitingUntil so that they can be run again
// that frame if necessary.
if ( !manualControl ) {
waitingUntil = gameLocal.time + gameLocal.msec;
}
}
/***********************************************************************
Script callable events
***********************************************************************/
/*
================
idThread::Event_TerminateThread
================
*/
void idThread::Event_TerminateThread( int num ) {
idThread *thread;
thread = GetThread( num );
KillThread( num );
}
/*
================
idThread::Event_Pause
================
*/
void idThread::Event_Pause( void ) {
Pause();
}
/*
================
idThread::Event_Wait
================
*/
void idThread::Event_Wait( float time ) {
WaitSec( time );
}
/*
================
idThread::Event_WaitFrame
================
*/
void idThread::Event_WaitFrame( void ) {
WaitFrame();
}
/*
================
idThread::Event_WaitFor
================
*/
void idThread::Event_WaitFor( idEntity *ent ) {
if ( ent && ent->RespondsTo( EV_Thread_SetCallback ) ) {
ent->ProcessEvent( &EV_Thread_SetCallback );
if ( gameLocal.program.GetReturnedInteger() ) {
Pause();
waitingFor = ent->entityNumber;
}
}
}
/*
================
idThread::Event_WaitForThread
================
*/
void idThread::Event_WaitForThread( int num ) {
idThread *thread;
thread = GetThread( num );
if ( !thread ) {
if ( g_debugScript.GetBool() ) {
// just print a warning and continue executing
Warning( "Thread %d not running", num );
}
} else {
Pause();
waitingForThread = thread;
}
}
/*
================
idThread::Event_Print
================
*/
void idThread::Event_Print( const char *text ) {
gameLocal.Printf( "%s", text );
}
/*
================
idThread::Event_PrintLn
================
*/
void idThread::Event_PrintLn( const char *text ) {
gameLocal.Printf( "%s\n", text );
}
/*
================
idThread::Event_Say
================
*/
void idThread::Event_Say( const char *text ) {
cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "say \"%s\"", text ) );
}
/*
================
idThread::Event_Assert
================
*/
void idThread::Event_Assert( float value ) {
// RAVEN BEGIN
// jnewquist: assert with a useful callstack, since this is script
#ifdef _DEBUG
if ( !value ) {
Error("Script assert fired");
}
#endif
// RAVEN END
}
/*
================
idThread::Event_Trigger
================
*/
void idThread::Event_Trigger( idEntity *ent ) {
if ( ent ) {
ent->Signal( SIG_TRIGGER );
ent->ProcessEvent( &EV_Activate, gameLocal.GetLocalPlayer() );
ent->TriggerGuis();
}
}
/*
================
idThread::Event_SetCvar
================
*/
void idThread::Event_SetCvar( const char *name, const char *value ) const {
cvarSystem->SetCVarString( name, value );
}
/*
================
idThread::Event_GetCvar
================
*/
void idThread::Event_GetCvar( const char *name ) const {
ReturnString( cvarSystem->GetCVarString( name ) );
}
/*
================
idThread::Event_Random
================
*/
void idThread::Event_Random( float range ) const {
float result;
result = gameLocal.random.RandomFloat();
ReturnFloat( range * result );
}
// RAVEN BEGIN
// abahr:
/*
================
idThread::Event_RandomInt
================
*/
void idThread::Event_RandomInt( float range ) const {
ReturnFloat( rvRandom::irand(0, range) );
}
// rjohnson: new blur special effect
void idThread::Event_SetSpecialEffect( int Effect, int Enabled ) {
renderSystem->SetSpecialEffect( (ESpecialEffectType)Effect, !!Enabled );
}
void idThread::Event_SetSpecialEffectParm( int Effect, int Parm, float Value ) {
renderSystem->SetSpecialEffectParm( (ESpecialEffectType)Effect, Parm, Value );
}
// RAVEN END
/*
================
idThread::Event_GetTime
================
*/
void idThread::Event_GetTime( void ) {
ReturnFloat( MS2SEC( gameLocal.realClientTime ) );
}
/*
================
idThread::Event_KillThread
================
*/
void idThread::Event_KillThread( const char *name ) {
KillThread( name );
}
/*
================
idThread::Event_GetEntity
================
*/
void idThread::Event_GetEntity( const char *name ) {
int entnum;
idEntity *ent;
assert( name );
if ( name[ 0 ] == '*' ) {
entnum = atoi( &name[ 1 ] );
if ( ( entnum < 0 ) || ( entnum >= MAX_GENTITIES ) ) {
Error( "Entity number in string out of range." );
}
ReturnEntity( gameLocal.entities[ entnum ] );
} else {
ent = gameLocal.FindEntity( name );
ReturnEntity( ent );
}
}
/*
================
idThread::Event_Spawn
================
*/
void idThread::Event_Spawn( const char *classname ) {
idEntity *ent;
spawnArgs.Set( "classname", classname );
gameLocal.SpawnEntityDef( spawnArgs, &ent );
ReturnEntity( ent );
spawnArgs.Clear();
}
/*
================
idThread::Event_CopySpawnArgs
================
*/
void idThread::Event_CopySpawnArgs( idEntity *ent ) {
spawnArgs.Copy( ent->spawnArgs );
}
/*
================
idThread::Event_SetSpawnArg
================
*/
void idThread::Event_SetSpawnArg( const char *key, const char *value ) {
spawnArgs.Set( key, value );
}
// RAVEN BEGIN
// kfuller: added events
/*
================
idThread::Event_SetSpawnVector
================
*/
void idThread::Event_SetSpawnVector( const char *key, idVec3 &vec) {
spawnArgs.SetVector(key, vec);
}
// RAVEN END
/*
================
idThread::Event_SpawnString
================
*/
void idThread::Event_SpawnString( const char *key, const char *defaultvalue ) {
const char *result;
spawnArgs.GetString( key, defaultvalue, &result );
ReturnString( result );
}
/*
================
idThread::Event_SpawnFloat
================
*/
void idThread::Event_SpawnFloat( const char *key, float defaultvalue ) {
float result;
spawnArgs.GetFloat( key, va( "%f", defaultvalue ), result );
ReturnFloat( result );
}
/*
================
idThread::Event_SpawnVector
================
*/
void idThread::Event_SpawnVector( const char *key, idVec3 &defaultvalue ) {
idVec3 result;
spawnArgs.GetVector( key, va( "%f %f %f", defaultvalue.x, defaultvalue.y, defaultvalue.z ), result );
ReturnVector( result );
}
/*
================
idThread::Event_ClearPersistantArgs
================
*/
void idThread::Event_ClearPersistantArgs( void ) {
gameLocal.persistentLevelInfo.Clear();
}
/*
================
idThread::Event_SetPersistantArg
================
*/
void idThread::Event_SetPersistantArg( const char *key, const char *value ) {
gameLocal.persistentLevelInfo.Set( key, value );
}
/*
================
idThread::Event_GetPersistantString
================
*/
void idThread::Event_GetPersistantString( const char *key ) {
const char *result;
gameLocal.persistentLevelInfo.GetString( key, "", &result );
ReturnString( result );
}
/*
================
idThread::Event_GetPersistantFloat
================
*/
void idThread::Event_GetPersistantFloat( const char *key ) {
float result;
gameLocal.persistentLevelInfo.GetFloat( key, "0", result );
ReturnFloat( result );
}
/*
================
idThread::Event_GetPersistantVector
================
*/
void idThread::Event_GetPersistantVector( const char *key ) {
idVec3 result;
gameLocal.persistentLevelInfo.GetVector( key, "0 0 0", result );
ReturnVector( result );
}
/*
================
idThread::Event_AngToForward
================
*/
void idThread::Event_AngToForward( idAngles &ang ) {
ReturnVector( ang.ToForward() );
}
/*
================
idThread::Event_AngToRight
================
*/
void idThread::Event_AngToRight( idAngles &ang ) {
idVec3 vec;
ang.ToVectors( NULL, &vec );
ReturnVector( vec );
}
/*
================
idThread::Event_AngToUp
================
*/
void idThread::Event_AngToUp( idAngles &ang ) {
idVec3 vec;
ang.ToVectors( NULL, NULL, &vec );
ReturnVector( vec );
}
// RAVEN BEGIN
// kfuller: added events
/*
================
idThread::Event_GetArcSine
================
*/
void idThread::Event_GetArcSine( float sinValue ) {
ReturnFloat( asinf( sinValue ) );
}
/*
================
idThread::Event_GetArcCosine
================
*/
void idThread::Event_GetArcCosine( float cosValue ) {
ReturnFloat( acosf( cosValue ) );
}
// RAVEN END
/*
================
idThread::Event_GetSine
================
*/
void idThread::Event_GetSine( float angle ) {
ReturnFloat( idMath::Sin( DEG2RAD( angle ) ) );
}
/*
================
idThread::Event_GetCosine
================
*/
void idThread::Event_GetCosine( float angle ) {
ReturnFloat( idMath::Cos( DEG2RAD( angle ) ) );
}
/*
================
idThread::Event_GetSquareRoot
================
*/
void idThread::Event_GetSquareRoot( float theSquare ) {
ReturnFloat( idMath::Sqrt( theSquare ) );
}
/*
================
idThread::Event_VecNormalize
================
*/
void idThread::Event_VecNormalize( idVec3 &vec ) {
idVec3 n;
n = vec;
n.Normalize();
ReturnVector( n );
}
/*
================
idThread::Event_VecLength
================
*/
void idThread::Event_VecLength( idVec3 &vec ) {
ReturnFloat( vec.Length() );
}
/*
================
idThread::Event_VecDotProduct
================
*/
void idThread::Event_VecDotProduct( idVec3 &vec1, idVec3 &vec2 ) {
ReturnFloat( vec1 * vec2 );
}
/*
================
idThread::Event_VecCrossProduct
================
*/
void idThread::Event_VecCrossProduct( idVec3 &vec1, idVec3 &vec2 ) {
ReturnVector( vec1.Cross( vec2 ) );
}
/*
================
idThread::Event_VecToAngles
================
*/
void idThread::Event_VecToAngles( idVec3 &vec ) {
idAngles ang = vec.ToAngles();
ReturnVector( idVec3( ang[0], ang[1], ang[2] ) );
}
// RAVEN BEGIN
// kef 12/2/02 -- made these into events
void idThread::Event_VecRotate(idVec3 &vecToBeRotated, idVec3 &rotateHowMuch)
{
idVec3 vecResult;
// VectorRotate3(vecToBeRotated, rotateHowMuch, vecResult);
gameLocal.Printf("'vecRotate' doesn't work -- I guess Keith should find a replacement for VectorRotate3 now...\n");
ReturnVector(vecResult);
}
// RAVEN END
/*
================
idThread::Event_OnSignal
================
*/
void idThread::Event_OnSignal( int signal, idEntity *ent, const char *func ) {
const function_t *function;
assert( func );
if ( !ent ) {
Error( "Entity not found" );
}
if ( ( signal < 0 ) || ( signal >= NUM_SIGNALS ) ) {
Error( "Signal out of range" );
}
function = gameLocal.program.FindFunction( func );
if ( !function ) {
Error( "Function '%s' not found", func );
}
ent->SetSignal( ( signalNum_t )signal, this, function );
}
/*
================
idThread::Event_ClearSignalThread
================
*/
void idThread::Event_ClearSignalThread( int signal, idEntity *ent ) {
if ( !ent ) {
Error( "Entity not found" );
}
if ( ( signal < 0 ) || ( signal >= NUM_SIGNALS ) ) {
Error( "Signal out of range" );
}
ent->ClearSignalThread( ( signalNum_t )signal, this );
}
// RAVEN BEGIN
// kfuller: added
/*
================
idThread::Event_ClearSignalAllThreads
================
*/
void idThread::Event_ClearSignalAllThreads( int signal, idEntity *ent ) {
if ( !ent ) {
Error( "Entity not found" );
}
if ( ( signal < 0 ) || ( signal >= NUM_SIGNALS ) ) {
Error( "Signal out of range" );
}
ent->ClearSignal(this, ( signalNum_t )signal);
}
// RAVEN END
/*
================
idThread::Event_SetCamera
================
*/
void idThread::Event_SetCamera( idEntity *ent ) {
if ( !ent ) {
Error( "Entity not found" );
return;
}
// RAVEN BEGIN
// jnewquist: Use accessor for static class type
if ( !ent->IsType( idCamera::GetClassType() ) ) {
// RAVEN END
Error( "Entity is not a camera" );
return;
}
gameLocal.SetCamera( ( idCamera * )ent );
}
/*
================
idThread::Event_FirstPerson
================
*/
void idThread::Event_FirstPerson( void ) {
gameLocal.SetCamera( NULL );
}
/*
================
idThread::Event_Trace
================
*/
void idThread::Event_Trace( const idVec3 &start, const idVec3 &end, const idVec3 &mins, const idVec3 &maxs, int contents_mask, idEntity *passEntity ) {
if ( mins == vec3_origin && maxs == vec3_origin ) {
// RAVEN BEGIN
// ddynerman: multiple clip worlds
gameLocal.TracePoint( NULL, trace, start, end, contents_mask, passEntity );
} else {
gameLocal.TraceBounds( NULL, trace, start, end, idBounds( mins, maxs ), contents_mask, passEntity );
// RAVEN END
}
ReturnFloat( trace.fraction );
}
/*
================
idThread::Event_TracePoint
================
*/
void idThread::Event_TracePoint( const idVec3 &start, const idVec3 &end, int contents_mask, idEntity *passEntity ) {
// RAVEN BEGIN
// ddynerman: multiple clip worlds
gameLocal.TracePoint( NULL, trace, start, end, contents_mask, passEntity );
// RAVEN END
ReturnFloat( trace.fraction );
}
/*
================
idThread::Event_GetTraceFraction
================
*/
void idThread::Event_GetTraceFraction( void ) {
ReturnFloat( trace.fraction );
}
/*
================
idThread::Event_GetTraceEndPos
================
*/
void idThread::Event_GetTraceEndPos( void ) {
ReturnVector( trace.endpos );
}
/*
================
idThread::Event_GetTraceNormal
================
*/
void idThread::Event_GetTraceNormal( void ) {
if ( trace.fraction < 1.0f ) {
ReturnVector( trace.c.normal );
} else {
ReturnVector( vec3_origin );
}
}
/*
================
idThread::Event_GetTraceEntity
================
*/
void idThread::Event_GetTraceEntity( void ) {
if ( trace.fraction < 1.0f ) {
ReturnEntity( gameLocal.entities[ trace.c.entityNum ] );
} else {
ReturnEntity( ( idEntity * )NULL );
}
}
/*
================
idThread::Event_GetTraceJoint
================
*/
void idThread::Event_GetTraceJoint( void ) {
if ( trace.fraction < 1.0f && trace.c.id < 0 ) {
idAFEntity_Base *af = static_cast<idAFEntity_Base *>( gameLocal.entities[ trace.c.entityNum ] );
// RAVEN BEGIN
// jnewquist: Use accessor for static class type
if ( af && af->IsType( idAFEntity_Base::GetClassType() ) && af->IsActiveAF() ) {
// RAVEN END
ReturnString( af->GetAnimator()->GetJointName( CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ) ) );
return;
}
}
ReturnString( "" );
}
/*
================
idThread::Event_GetTraceBody
================
*/
void idThread::Event_GetTraceBody( void ) {
if ( trace.fraction < 1.0f && trace.c.id < 0 ) {
idAFEntity_Base *af = static_cast<idAFEntity_Base *>( gameLocal.entities[ trace.c.entityNum ] );
// RAVEN BEGIN
// jnewquist: Use accessor for static class type
if ( af && af->IsType( idAFEntity_Base::GetClassType() ) && af->IsActiveAF() ) {
// RAVEN END
int bodyId = af->BodyForClipModelId( trace.c.id );
idAFBody *body = af->GetAFPhysics()->GetBody( bodyId );
if ( body ) {
ReturnString( body->GetName() );
return;
}
}
}
ReturnString( "" );
}
/*
================
idThread::Event_FadeIn
================
*/
void idThread::Event_FadeIn( idVec3 &color, float time ) {
idVec4 fadeColor;
idPlayer *player;
player = gameLocal.GetLocalPlayer();
if ( player ) {
fadeColor.Set( color[ 0 ], color[ 1 ], color[ 2 ], 0.0f );
player->playerView.Fade(fadeColor, SEC2MS( time ) );
}
}
/*
================
idThread::Event_FadeOut
================
*/
void idThread::Event_FadeOut( idVec3 &color, float time ) {
idVec4 fadeColor;
idPlayer *player;
player = gameLocal.GetLocalPlayer();
if ( player ) {
fadeColor.Set( color[ 0 ], color[ 1 ], color[ 2 ], 1.0f );
player->playerView.Fade(fadeColor, SEC2MS( time ) );
}
}
/*
================
idThread::Event_FadeTo
================
*/
void idThread::Event_FadeTo( idVec3 &color, float alpha, float time ) {
idVec4 fadeColor;
idPlayer *player;
player = gameLocal.GetLocalPlayer();
if ( player ) {
fadeColor.Set( color[ 0 ], color[ 1 ], color[ 2 ], alpha );
player->playerView.Fade(fadeColor, SEC2MS( time ) );
}
}
/*
================
idThread::Event_SetShaderParm
================
*/
void idThread::Event_SetShaderParm( int parmnum, float value ) {
if ( ( parmnum < 0 ) || ( parmnum >= MAX_GLOBAL_SHADER_PARMS ) ) {
Error( "shader parm index (%d) out of range", parmnum );
}
gameLocal.globalShaderParms[ parmnum ] = value;
}
/*
================
idThread::Event_StartMusic
================
*/
void idThread::Event_StartMusic( const char *text ) {
soundSystem->PlayShaderDirectly( SOUNDWORLD_GAME, text );
}
/*
================
idThread::Event_Warning
================
*/
void idThread::Event_Warning( const char *text ) {
Warning( "%s", text );
}
/*
================
idThread::Event_Error
================
*/
void idThread::Event_Error( const char *text ) {
Error( "%s", text );
}
/*
================
idThread::Event_StrLen
================
*/
void idThread::Event_StrLen( const char *string ) {
int len;
len = strlen( string );
idThread::ReturnInt( len );
}
/*
================
idThread::Event_StrLeft
================
*/
void idThread::Event_StrLeft( const char *string, int num ) {
int len;
if ( num < 0 ) {
idThread::ReturnString( "" );
return;
}
len = strlen( string );
if ( len < num ) {
idThread::ReturnString( string );
return;
}
idStr result( string, 0, num );
idThread::ReturnString( result );
}
/*
================
idThread::Event_StrRight
================
*/
void idThread::Event_StrRight( const char *string, int num ) {
int len;
if ( num < 0 ) {
idThread::ReturnString( "" );
return;
}
len = strlen( string );
if ( len < num ) {
idThread::ReturnString( string );
return;
}
idThread::ReturnString( string + len - num );
}
/*
================
idThread::Event_StrSkip
================
*/
void idThread::Event_StrSkip( const char *string, int num ) {
int len;
if ( num < 0 ) {
idThread::ReturnString( string );
return;
}
len = strlen( string );
if ( len < num ) {
idThread::ReturnString( "" );
return;
}
idThread::ReturnString( string + num );
}
/*
================
idThread::Event_StrMid
================
*/
void idThread::Event_StrMid( const char *string, int start, int num ) {
int len;
if ( num < 0 ) {
idThread::ReturnString( "" );
return;
}
if ( start < 0 ) {
start = 0;
}
len = strlen( string );
if ( start > len ) {
start = len;
}
if ( start + num > len ) {
num = len - start;
}
idStr result( string, start, start + num );
idThread::ReturnString( result );
}
/*
================
idThread::Event_StrToFloat( const char *string )
================
*/
void idThread::Event_StrToFloat( const char *string ) {
float result;
result = atof( string );
idThread::ReturnFloat( result );
}
/*
================
idThread::Event_RadiusDamage
================
*/
void idThread::Event_RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignore, const char *damageDefName, float dmgPower ) {
gameLocal.RadiusDamage( origin, inflictor, attacker, ignore, ignore, damageDefName, dmgPower );
}
/*
================
idThread::Event_IsClient
================
*/
void idThread::Event_IsClient( void ) {
idThread::ReturnFloat( gameLocal.isClient );
}
/*
================
idThread::Event_IsMultiplayer
================
*/
void idThread::Event_IsMultiplayer( void ) {
idThread::ReturnFloat( gameLocal.isMultiplayer );
}
/*
================
idThread::Event_GetFrameTime
================
*/
void idThread::Event_GetFrameTime( void ) {
idThread::ReturnFloat( MS2SEC( gameLocal.msec ) );
}
/*
================
idThread::Event_GetTicsPerSecond
================
*/
void idThread::Event_GetTicsPerSecond( void ) {
idThread::ReturnFloat( gameLocal.GetMHz() );
}
/*
================
idThread::Event_CacheSoundShader
================
*/
void idThread::Event_CacheSoundShader( const char *soundName ) {
declManager->FindSound( soundName );
}
/*
================
idThread::Event_DebugLine
================
*/
void idThread::Event_DebugLine( const idVec3 &color, const idVec3 &start, const idVec3 &end, const float lifetime ) {
gameRenderWorld->DebugLine( idVec4( color.x, color.y, color.z, 0.0f ), start, end, SEC2MS( lifetime ) );
}
/*
================
idThread::Event_DebugArrow
================
*/
void idThread::Event_DebugArrow( const idVec3 &color, const idVec3 &start, const idVec3 &end, const int size, const float lifetime ) {
gameRenderWorld->DebugArrow( idVec4( color.x, color.y, color.z, 0.0f ), start, end, size, SEC2MS( lifetime ) );
}
/*
================
idThread::Event_DebugCircle
================
*/
void idThread::Event_DebugCircle( const idVec3 &color, const idVec3 &origin, const idVec3 &dir, const float radius, const int numSteps, const float lifetime ) {
gameRenderWorld->DebugCircle( idVec4( color.x, color.y, color.z, 0.0f ), origin, dir, radius, numSteps, SEC2MS( lifetime ) );
}
/*
================
idThread::Event_DebugBounds
================
*/
void idThread::Event_DebugBounds( const idVec3 &color, const idVec3 &mins, const idVec3 &maxs, const float lifetime ) {
gameRenderWorld->DebugBounds( idVec4( color.x, color.y, color.z, 0.0f ), idBounds( mins, maxs ), vec3_origin, SEC2MS( lifetime ) );
}
/*
================
idThread::Event_DrawText
================
*/
void idThread::Event_DrawText( const char *text, const idVec3 &origin, float scale, const idVec3 &color, const int align, const float lifetime ) {
gameRenderWorld->DrawText( text, origin, scale, idVec4( color.x, color.y, color.z, 0.0f ), gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), align, SEC2MS( lifetime ) );
}
/*
================
idThread::Event_InfluenceActive
================
*/
void idThread::Event_InfluenceActive( void ) {
idPlayer *player;
player = gameLocal.GetLocalPlayer();
if ( player && player->GetInfluenceLevel() ) {
idThread::ReturnInt( true );
} else {
idThread::ReturnInt( false );
}
}
// RAVEN BEGIN
// kfuller: added events
/*
================
idThread::Event_PlayWorldEffect
================
*/
void idThread::Event_PlayWorldEffect( const char *effectName, idVec3 &org, idVec3 &angle ) {
gameLocal.PlayEffect ( ( const idDecl * )declManager->FindEffect( effectName ), org, angle.ToMat3() );
}
// abahr:
/*
================
idThread::Event_ReferenceScriptObjectProxy
================
*/
void idThread::Event_ReferenceScriptObjectProxy( const char* scriptObjectName ) {
ReturnEntity( gameLocal.ReferenceScriptObjectProxy(scriptObjectName) );
Event_WaitFrame();// Needed because the constructor call is delayed by one frame
}
/*
================
idThread::Event_ReleaseScriptObjectProxy
================
*/
void idThread::Event_ReleaseScriptObjectProxy( const char* proxyName ) {
gameLocal.ReleaseScriptObjectProxy( proxyName );
Event_WaitFrame();// Needed because the destructor call is delayed by one frame
}
/*
================
idThread::Event_ClampFloat
================
*/
void idThread::Event_ClampFloat( float min, float max, float val ) {
ReturnFloat( idMath::ClampFloat(min, max, val) );
}
/*
================
idThread::Event_MinFloat
================
*/
void idThread::Event_MinFloat( float val1, float val2 ) {
ReturnFloat( Min<float>(val1, val2) );
}
/*
================
idThread::Event_MaxFloat
================
*/
void idThread::Event_MaxFloat( float val1, float val2 ) {
ReturnFloat( Max<float>(val1, val2) );
}
/*
================
idThread::Event_StrFind
================
*/
void idThread::Event_StrFind( idStr& sourceStr, idStr& subStr ) {
idThread::ReturnInt( sourceStr.Find(subStr.c_str()) );
}
// asalmon: award achievement
/*
================
idThread::Event_AwardAchievement
================
*/
void idThread::Event_AwardAchievement( const char *name ) {
#ifdef _XENON
Live()->AwardAchievement(name);
#endif
}
// twhitaker: ceil, floor and intVal
/*
================
idThread::Event_GetCeil
================
*/
void idThread::Event_GetCeil( float val ) {
ReturnFloat( idMath::Ceil( val ) );
}
/*
================
idThread::Event_GetFloor
================
*/
void idThread::Event_GetFloor( float val ) {
ReturnFloat( idMath::Floor( val ) );
}
/*
================
idThread::Event_ToInt
================
*/
void idThread::Event_ToInt( float val ) {
ReturnFloat( idMath::Ftoi( val ) );
// ReturnFloat( idMath::FtoiFast( val ) );
}
// jdischler: send named event string to specified gui
/*
===============================
idThread::Event_SendNamedEvent
===============================
*/
void idThread::Event_SendNamedEvent( int guiEnum, const char *namedEvent ) {
typedef enum {
SNE_PLAYERHUD = 0,
SNE_CINEMATICHUD,
SNE_VEHICLECHUD,
SNE_CURSORHUD,
};
idPlayer *player = gameLocal.GetLocalPlayer();
if ( !player ) {
return;
}
switch( guiEnum ) {
case SNE_PLAYERHUD:
if ( player->hud ) {
player->hud->HandleNamedEvent( namedEvent );
}
break;
case SNE_CINEMATICHUD:
if ( player->cinematicHud ) {
player->cinematicHud->HandleNamedEvent( namedEvent );
}
break;
case SNE_VEHICLECHUD:
// twhitaker: I'd really just rather use player->GetHud() ... which returns the vehicle hud if the player is in a vehicle
// but this way the scripter will be able to strictly enforce which hud the named event gets played on. See idPlayer::GetHud()
if ( player->vehicleController.GetVehicle() ) {
idUserInterface * hud = player->vehicleController.GetVehicle()->GetHud();
if ( hud ) {
hud->HandleNamedEvent( namedEvent );
}
}
break;
case SNE_CURSORHUD:
if ( player->GetCursorGUI() ) {
player->GetCursorGUI()->HandleNamedEvent( namedEvent );
}
break;
}
}
/*
================
idThread::Event_SetMatSort
================
*/
void idThread::Event_SetMatSort( const char *name, const char *val ) const {
const idMaterial *mat = declManager->FindMaterial( name );
if ( mat ) {
int srt = SS_DECAL;
if ( idStr::Icmp( val, "SS_MIN" ) == 0 ) {
srt = SS_MIN;
} else if ( idStr::Icmp( val, "SS_SUBVIEW" ) == 0 ) {
srt = SS_SUBVIEW;
} else if ( idStr::Icmp( val, "SS_PREGUI" ) == 0 ) {
srt = SS_PREGUI;
} else if ( idStr::Icmp( val, "SS_GUI" ) == 0 ) {
srt = SS_GUI;
} else if ( idStr::Icmp( val, "SS_BAD" ) == 0 ) {
srt = SS_BAD;
} else if ( idStr::Icmp( val, "SS_OPAQUE" ) == 0 ) {
srt = SS_OPAQUE;
} else if ( idStr::Icmp( val, "SS_PORTAL_SKY" ) == 0 ) {
srt = SS_PORTAL_SKY;
} else if ( idStr::Icmp( val, "SS_DECAL" ) == 0 ) {
srt = SS_DECAL;
} else if ( idStr::Icmp( val, "SS_FAR" ) == 0 ) {
srt = SS_FAR;
} else if ( idStr::Icmp( val, "SS_MEDIUM" ) == 0 ) {
srt = SS_MEDIUM;
} else if ( idStr::Icmp( val, "SS_CLOSE" ) == 0 ) {
srt = SS_CLOSE;
} else if ( idStr::Icmp( val, "SS_ALMOST_NEAREST" ) == 0 ) {
srt = SS_ALMOST_NEAREST;
} else if ( idStr::Icmp( val, "SS_NEAREST" ) == 0 ) {
srt = SS_NEAREST;
} else if ( idStr::Icmp( val, "SS_POST_PROCESS" ) == 0 ) {
srt = SS_POST_PROCESS;
}
mat->SetSort( srt );
}
}
// jdischler: Adding ability to create texture streams from scripts
/*
================
idThread::Event_BeginManualStreaming
================
*/
void idThread::Event_BeginManualStreaming()
{
}
/*
================
idThread::Event_EndManualStreaming
================
*/
void idThread::Event_EndManualStreaming()
{
}
// RAVEN END