/* =========================================================================== IceTech GPL Source Code Copyright (C) 2026 Justin Marshall This file is part of the IceTech GPL Source Code ("IceTech Source Code"). IceTech Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. IceTech Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with IceTech Source Code. If not, see . In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com =========================================================================== */ #ifndef __SCRIPT_THREAD_H__ #define __SCRIPT_THREAD_H__ #include "script/Script_Interpreter.h" #include "gamesys/Class.h" #include "gamesys/Event.h" class idThread : public idClass { private: static idThread *currentThread; idThread *waitingForThread; int waitingFor; int waitingUntil; idInterpreter interpreter; idDict spawnArgs; int threadNum; idStr threadName; int lastExecuteTime; int creationTime; bool manualControl; static int threadIndex; static idList threadList; static trace_t trace; void Init( void ); void Pause( void ); ID_SCRIPT_EVENT( "", 0 ) void Event_Execute( void ); ID_SCRIPT_EVENT( "threadname", 0 ) void Event_SetThreadName( const char *name ); // // script callable Events // ID_SCRIPT_EVENT( "terminate", 0 ) void Event_TerminateThread( int num ); ID_SCRIPT_EVENT( "pause", 0 ) void Event_Pause( void ); ID_SCRIPT_EVENT( "wait", 0 ) void Event_Wait( float time ); ID_SCRIPT_EVENT( "waitFrame", 0 ) void Event_WaitFrame( void ); ID_SCRIPT_EVENT( "waitFor", 0 ) void Event_WaitFor( idEntity *ent ); ID_SCRIPT_EVENT( "waitForThread", 0 ) void Event_WaitForThread( int num ); ID_SCRIPT_EVENT( "print", 0 ) void Event_Print( const char *text ); ID_SCRIPT_EVENT( "println", 0 ) void Event_PrintLn( const char *text ); ID_SCRIPT_EVENT( "say", 0 ) void Event_Say( const char *text ); ID_SCRIPT_EVENT( "assert", 0 ) void Event_Assert( float value ); ID_SCRIPT_EVENT( "trigger", 0 ) void Event_Trigger( idEntity *ent ); ID_SCRIPT_EVENT( "setcvar", 0 ) void Event_SetCvar( const char *name, const char *value ) const; ID_SCRIPT_EVENT( "getcvar", 's' ) void Event_GetCvar( const char *name ) const; ID_SCRIPT_EVENT( "random", 'f' ) void Event_Random( float range ) const; ID_SCRIPT_EVENT( "getTime", 'f' ) void Event_GetTime( void ); ID_SCRIPT_EVENT( "killthread", 0 ) void Event_KillThread( const char *name ); ID_SCRIPT_EVENT( "getEntity", 'e' ) void Event_GetEntity( const char *name ); ID_SCRIPT_EVENT( "spawn", 'e' ) void Event_Spawn( const char *classname ); ID_SCRIPT_EVENT( "copySpawnArgs", 0 ) void Event_CopySpawnArgs( idEntity *ent ); ID_SCRIPT_EVENT( "setSpawnArg", 0 ) void Event_SetSpawnArg( const char *key, const char *value ); ID_SCRIPT_EVENT( "SpawnString", 's' ) void Event_SpawnString( const char *key, const char *defaultvalue ); ID_SCRIPT_EVENT( "SpawnFloat", 'f' ) void Event_SpawnFloat( const char *key, float defaultvalue ); ID_SCRIPT_EVENT( "SpawnVector", 'v' ) void Event_SpawnVector( const char *key, idVec3 &defaultvalue ); ID_SCRIPT_EVENT( "clearPersistantArgs", 0 ) void Event_ClearPersistantArgs( void ); ID_SCRIPT_EVENT( "setPersistantArg", 0 ) void Event_SetPersistantArg( const char *key, const char *value ); ID_SCRIPT_EVENT( "getPersistantString", 's' ) void Event_GetPersistantString( const char *key ); ID_SCRIPT_EVENT( "getPersistantFloat", 'f' ) void Event_GetPersistantFloat( const char *key ); ID_SCRIPT_EVENT( "getPersistantVector", 'v' ) void Event_GetPersistantVector( const char *key ); ID_SCRIPT_EVENT( "angToForward", 'v' ) void Event_AngToForward( idAngles &ang ); ID_SCRIPT_EVENT( "angToRight", 'v' ) void Event_AngToRight( idAngles &ang ); ID_SCRIPT_EVENT( "angToUp", 'v' ) void Event_AngToUp( idAngles &ang ); ID_SCRIPT_EVENT( "sin", 'f' ) void Event_GetSine( float angle ); ID_SCRIPT_EVENT( "cos", 'f' ) void Event_GetCosine( float angle ); ID_SCRIPT_EVENT( "sqrt", 'f' ) void Event_GetSquareRoot( float theSquare ); ID_SCRIPT_EVENT( "vecNormalize", 'v' ) void Event_VecNormalize( idVec3 &vec ); ID_SCRIPT_EVENT( "vecLength", 'f' ) void Event_VecLength( idVec3 &vec ); ID_SCRIPT_EVENT( "DotProduct", 'f' ) void Event_VecDotProduct( idVec3 &vec1, idVec3 &vec2 ); ID_SCRIPT_EVENT( "CrossProduct", 'v' ) void Event_VecCrossProduct( idVec3 &vec1, idVec3 &vec2 ); ID_SCRIPT_EVENT( "VecToAngles", 'v' ) void Event_VecToAngles( idVec3 &vec ); ID_SCRIPT_EVENT( "onSignal", 0 ) void Event_OnSignal( int signal, idEntity *ent, const char *func ); ID_SCRIPT_EVENT( "clearSignalThread", 0 ) void Event_ClearSignalThread( int signal, idEntity *ent ); ID_SCRIPT_EVENT( "setCamera", 0 ) void Event_SetCamera( idEntity *ent ); ID_SCRIPT_EVENT( "firstPerson", 0 ) void Event_FirstPerson( void ); ID_SCRIPT_EVENT( "trace", 'f' ) void Event_Trace( const idVec3 &start, const idVec3 &end, const idVec3 &mins, const idVec3 &maxs, int contents_mask, idEntity *passEntity ); ID_SCRIPT_EVENT( "tracePoint", 'f' ) void Event_TracePoint( const idVec3 &start, const idVec3 &end, int contents_mask, idEntity *passEntity ); ID_SCRIPT_EVENT( "getTraceFraction", 'f' ) void Event_GetTraceFraction( void ); ID_SCRIPT_EVENT( "getTraceEndPos", 'v' ) void Event_GetTraceEndPos( void ); ID_SCRIPT_EVENT( "getTraceNormal", 'v' ) void Event_GetTraceNormal( void ); ID_SCRIPT_EVENT( "getTraceEntity", 'e' ) void Event_GetTraceEntity( void ); ID_SCRIPT_EVENT( "getTraceJoint", 's' ) void Event_GetTraceJoint( void ); ID_SCRIPT_EVENT( "getTraceBody", 's' ) void Event_GetTraceBody( void ); ID_SCRIPT_EVENT( "fadeIn", 0 ) void Event_FadeIn( idVec3 &color, float time ); ID_SCRIPT_EVENT( "fadeOut", 0 ) void Event_FadeOut( idVec3 &color, float time ); ID_SCRIPT_EVENT( "fadeTo", 0 ) void Event_FadeTo( idVec3 &color, float alpha, float time ); ID_SCRIPT_EVENT( "setShaderParm", 0 ) void Event_SetShaderParm( int parmnum, float value ); ID_SCRIPT_EVENT( "music", 0 ) void Event_StartMusic( const char *name ); ID_SCRIPT_EVENT( "warning", 0 ) void Event_Warning( const char *text ); ID_SCRIPT_EVENT( "error", 0 ) void Event_Error( const char *text ); ID_SCRIPT_EVENT( "strLength", 'd' ) void Event_StrLen( const char *string ); ID_SCRIPT_EVENT( "strLeft", 's' ) void Event_StrLeft( const char *string, int num ); ID_SCRIPT_EVENT( "strRight", 's' ) void Event_StrRight( const char *string, int num ); ID_SCRIPT_EVENT( "strSkip", 's' ) void Event_StrSkip( const char *string, int num ); ID_SCRIPT_EVENT( "strMid", 's' ) void Event_StrMid( const char *string, int start, int num ); ID_SCRIPT_EVENT( "strToFloat", 'f' ) void Event_StrToFloat( const char *string ); ID_SCRIPT_EVENT( "radiusDamage", 0 ) void Event_RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignore, const char *damageDefName, float dmgPower ); ID_SCRIPT_EVENT( "isClient", 'f' ) void Event_IsClient( void ); ID_SCRIPT_EVENT( "isMultiplayer", 'f' ) void Event_IsMultiplayer( void ); ID_SCRIPT_EVENT( "getFrameTime", 'f' ) void Event_GetFrameTime( void ); ID_SCRIPT_EVENT( "getTicsPerSecond", 'f' ) void Event_GetTicsPerSecond( void ); ID_SCRIPT_EVENT( "cacheSoundShader", 0 ) void Event_CacheSoundShader( const char *soundName ); ID_SCRIPT_EVENT( "debugLine", 0 ) void Event_DebugLine( const idVec3 &color, const idVec3 &start, const idVec3 &end, const float lifetime ); ID_SCRIPT_EVENT( "debugArrow", 0 ) void Event_DebugArrow( const idVec3 &color, const idVec3 &start, const idVec3 &end, const int size, const float lifetime ); ID_SCRIPT_EVENT( "debugCircle", 0 ) void Event_DebugCircle( const idVec3 &color, const idVec3 &origin, const idVec3 &dir, const float radius, const int numSteps, const float lifetime ); ID_SCRIPT_EVENT( "debugBounds", 0 ) void Event_DebugBounds( const idVec3 &color, const idVec3 &mins, const idVec3 &maxs, const float lifetime ); ID_SCRIPT_EVENT( "drawText", 0 ) void Event_DrawText( const char *text, const idVec3 &origin, float scale, const idVec3 &color, const int align, const float lifetime ); ID_SCRIPT_EVENT( "influenceActive", 'd' ) void Event_InfluenceActive( void ); public: CLASS_PROTOTYPE( idThread ); idThread(); idThread( idEntity *self, const function_t *func ); idThread( const function_t *func ); idThread( idInterpreter *source, const function_t *func, int args ); idThread( idInterpreter *source, idEntity *self, const function_t *func, int args ); virtual ~idThread(); // tells the thread manager not to delete this thread when it ends void ManualDelete( void ); // save games void Save( idSaveGame *savefile ) const; // archives object for save game file void Restore( idRestoreGame *savefile ); // unarchives object from save game file void EnableDebugInfo( void ) { interpreter.debug = true; }; void DisableDebugInfo( void ) { interpreter.debug = false; }; void WaitMS( int time ); void WaitSec( float time ); void WaitFrame( void ); // NOTE: If this is called from within a event called by this thread, the function arguments will be invalid after calling this function. void CallFunction( const function_t *func, bool clearStack ); // NOTE: If this is called from within a event called by this thread, the function arguments will be invalid after calling this function. void CallFunction( idEntity *obj, const function_t *func, bool clearStack ); void DisplayInfo(); static idThread *GetThread( int num ); static void ListThreads_f( const idCmdArgs &args ); static void Restart( void ); static void ObjectMoveDone( int threadnum, idEntity *obj ); static idList& GetThreads ( void ); bool IsDoneProcessing ( void ); bool IsDying ( void ); void End( void ); static void KillThread( const char *name ); static void KillThread( int num ); bool Execute( void ); void ManualControl( void ) { manualControl = true; CancelEvents( &EV_idThread_Execute); }; void DoneProcessing( void ) { interpreter.doneProcessing = true; }; void ContinueProcessing( void ) { interpreter.doneProcessing = false; }; bool ThreadDying( void ) { return interpreter.threadDying; }; void EndThread( void ) { interpreter.threadDying = true; }; bool IsWaiting( void ); void ClearWaitFor( void ); bool IsWaitingFor( idEntity *obj ); void ObjectMoveDone( idEntity *obj ); void ThreadCallback( idThread *thread ); void DelayedStart( int delay ); bool Start( void ); idThread *WaitingOnThread( void ); void SetThreadNum( int num ); int GetThreadNum( void ); void SetThreadName( const char *name ); const char *GetThreadName( void ); void Error( const char *fmt, ... ) const id_attribute((format(printf,2,3))); void Warning( const char *fmt, ... ) const id_attribute((format(printf,2,3))); static idThread *CurrentThread( void ); static int CurrentThreadNum( void ); static bool BeginMultiFrameEvent( idEntity *ent, const idEventDef *event ); static void EndMultiFrameEvent( idEntity *ent, const idEventDef *event ); static void ReturnString( const char *text ); static void ReturnFloat( float value ); static void ReturnInt( int value ); static void ReturnVector( idVec3 const &vec ); static void ReturnEntity( idEntity *ent ); }; /* ================ idThread::WaitingOnThread ================ */ ID_INLINE idThread *idThread::WaitingOnThread( void ) { return waitingForThread; } /* ================ idThread::SetThreadNum ================ */ ID_INLINE void idThread::SetThreadNum( int num ) { threadNum = num; } /* ================ idThread::GetThreadNum ================ */ ID_INLINE int idThread::GetThreadNum( void ) { return threadNum; } /* ================ idThread::GetThreadName ================ */ ID_INLINE const char *idThread::GetThreadName( void ) { return threadName.c_str(); } /* ================ idThread::GetThreads ================ */ ID_INLINE idList& idThread::GetThreads ( void ) { return threadList; } /* ================ idThread::IsDoneProcessing ================ */ ID_INLINE bool idThread::IsDoneProcessing ( void ) { return interpreter.doneProcessing; } /* ================ idThread::IsDying ================ */ ID_INLINE bool idThread::IsDying ( void ) { return interpreter.threadDying; } #endif /* !__SCRIPT_THREAD_H__ */