2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program 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 2
of the License , or ( at your option ) any later version .
This program 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 this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2004-09-08 05:09:33 +00:00
# include "qwsvdef.h"
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
//okay, so these are a quick but easy hack
void ED_Print ( struct progfuncs_s * progfuncs , struct edict_s * ed ) ;
2004-09-13 02:22:02 +00:00
int PR_EnableEBFSBuiltin ( char * name , int binum ) ;
2004-08-23 00:15:46 +00:00
void PR_CleanLogText_Init ( void ) ;
cvar_t nomonsters = { " nomonsters " , " 0 " } ;
cvar_t gamecfg = { " gamecfg " , " 0 " } ;
cvar_t scratch1 = { " scratch1 " , " 0 " } ;
cvar_t scratch2 = { " scratch2 " , " 0 " } ;
cvar_t scratch3 = { " scratch3 " , " 0 " } ;
cvar_t scratch4 = { " scratch4 " , " 0 " } ;
cvar_t savedgamecfg = { " savedgamecfg " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t saved1 = { " saved1 " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t saved2 = { " saved2 " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t saved3 = { " saved3 " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t saved4 = { " saved4 " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t temp1 = { " temp1 " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t noexit = { " noexit " , " 0 " , NULL } ;
2004-09-30 22:22:32 +00:00
cvar_t pr_maxedicts = { " pr_maxedicts " , " 600 " , NULL , CVAR_LATCH } ;
2004-08-23 00:15:46 +00:00
cvar_t pr_imitatemvdsv = { " pr_imitatemvdsv " , " 0 " , NULL , CVAR_LATCH } ;
2004-09-30 22:22:32 +00:00
cvar_t pr_fixbrokenqccarrays = { " pr_fixbrokenqccarrays " , " 1 " , NULL , CVAR_LATCH } ;
2004-08-23 00:15:46 +00:00
2004-11-20 00:55:29 +00:00
cvar_t pr_no_playerphysics = { " pr_no_playerphysics " , " 0 " , NULL , CVAR_LATCH } ;
2004-08-23 00:15:46 +00:00
cvar_t progs = { " progs " , " " , NULL , CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER } ;
cvar_t qc_nonetaccess = { " qc_nonetaccess " , " 0 " } ; //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc.
cvar_t pr_overridebuiltins = { " pr_overridebuiltins " , " 1 " } ;
2004-08-31 23:58:18 +00:00
cvar_t pr_compatabilitytest = { " pr_compatabilitytest " , " 0 " , NULL , CVAR_LATCH } ;
2004-08-23 00:15:46 +00:00
cvar_t sv_addon [ MAXADDONS ] ;
char cvargroup_progs [ ] = " Progs variables " ;
2004-10-13 06:37:44 +00:00
evalc_t evalc_idealpitch , evalc_pitch_speed ;
2004-08-23 00:15:46 +00:00
int pr_teamfield ;
void PR_ClearThreads ( void ) ;
2005-04-16 16:21:27 +00:00
void PR_fclose_progs ( progfuncs_t * ) ;
2005-05-20 03:32:53 +00:00
void PF_InitTempStrings ( progfuncs_t * prinst ) ;
2004-08-23 00:15:46 +00:00
typedef struct {
//for func finding and swapping.
char * name ;
//c function to call
builtin_t bifunc ;
//most of the next two are the same, but they follow different family trees.
//It depends on the progs type being loaded as to which is used.
int nqnum ; //standard nq.
int qwnum ; //standard qw.
int h2num ; //standard hexen2
int ebfsnum ; //extra functions, these exist ONLY after being checked for.
} BuiltinList_t ;
2004-10-13 06:37:44 +00:00
builtin_t pr_builtin [ 1024 ] ;
2004-08-23 00:15:46 +00:00
extern BuiltinList_t BuiltinList [ ] ;
qboolean pr_udc_exteffect_enabled ;
func_t SpectatorConnect ;
func_t SpectatorThink ;
func_t SpectatorDisconnect ;
func_t ChatMessage ;
func_t getplayerstat [ MAX_CL_STATS ] ;
func_t getplayerstati [ MAX_CL_STATS ] ;
//mvdsv stuff
func_t mod_UserCmd , SV_ParseClientCommand ;
func_t mod_ConsoleCmd ;
func_t UserInfo_Changed ;
func_t localinfoChanged ;
func_t SV_PlayerPhysicsQC ; //DP's DP_SV_PLAYERPHYSICS extension
func_t EndFrameQC ;
qboolean pr_items2 ;
nqglobalvars_t realpr_nqglobal_struct ;
nqglobalvars_t * pr_nqglobal_struct = & realpr_nqglobal_struct ;
progfuncs_t * svprogfuncs ;
progparms_t svprogparms ;
progstype_t progstype ;
void PR_RegisterSVBuiltins ( void ) ;
void PR_RegisterFields ( void ) ;
void PR_ResetBuiltins ( progstype_t type ) ;
char * QC_ProgsNameForEnt ( edict_t * ent )
{
return " ? " ;
}
int pr_edict_size ;
int COM_FileSize ( char * path ) ;
pbool QC_WriteFile ( char * name , void * data , int len )
{
char buffer [ 256 ] ;
2004-09-04 17:52:32 +00:00
sprintf ( buffer , " %s " , name ) ;
2004-08-23 00:15:46 +00:00
COM_WriteFile ( buffer , data , len ) ;
return true ;
}
void ED_Spawned ( struct edict_s * ent )
{
2005-03-28 00:11:59 +00:00
ent - > v - > dimension_see = 255 ;
ent - > v - > dimension_seen = 255 ;
ent - > v - > dimension_ghost = 0 ;
ent - > v - > dimension_solid = 255 ;
ent - > v - > dimension_hit = 255 ;
2005-02-28 07:16:19 +00:00
2005-03-28 00:11:59 +00:00
ent - > v - > Version = sv . csqcentversion [ ent - > entnum ] + 1 ;
2004-08-23 00:15:46 +00:00
}
pbool ED_CanFree ( edict_t * ed )
{
if ( ed = = sv . edicts )
{
Con_TPrintf ( STL_CANTFREEWORLD ) ;
2004-11-21 07:31:26 +00:00
* svprogfuncs - > pr_trace = 1 ;
2004-08-23 00:15:46 +00:00
return false ;
}
if ( NUM_FOR_EDICT ( svprogfuncs , ed ) < = sv . allocated_client_slots )
{
Con_TPrintf ( STL_CANTFREEPLAYERS ) ;
2004-11-21 07:31:26 +00:00
* svprogfuncs - > pr_trace = 1 ;
2004-08-23 00:15:46 +00:00
return false ;
}
SV_UnlinkEdict ( ed ) ; // unlink from world bsp
2005-03-28 00:11:59 +00:00
ed - > v - > model = 0 ;
ed - > v - > takedamage = 0 ;
ed - > v - > modelindex = 0 ;
ed - > v - > colormap = 0 ;
ed - > v - > skin = 0 ;
ed - > v - > frame = 0 ;
VectorCopy ( vec3_origin , ed - > v - > origin ) ;
VectorCopy ( vec3_origin , ed - > v - > angles ) ;
ed - > v - > nextthink = 0 ;
ed - > v - > think = 0 ;
ed - > v - > solid = 0 ;
ed - > v - > SendEntity = 0 ;
sv . csqcentversion [ ed - > entnum ] = ed - > v - > Version + 1 ;
2005-02-28 07:16:19 +00:00
2004-08-23 00:15:46 +00:00
return true ;
}
void StateOp ( progfuncs_t * prinst , float var , func_t func )
{
2005-03-28 00:11:59 +00:00
entvars_t * vars = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) - > v ;
2004-08-23 00:15:46 +00:00
if ( progstype = = PROG_H2 )
vars - > nextthink = pr_global_struct - > time + 0.05 ;
else
vars - > nextthink = pr_global_struct - > time + 0.1 ;
vars - > think = func ;
vars - > frame = var ;
}
void CStateOp ( progfuncs_t * prinst , float startFrame , float endFrame , func_t currentfunc )
{
2005-03-28 00:11:59 +00:00
entvars_t * vars = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) - > v ;
2004-08-23 00:15:46 +00:00
vars - > nextthink = pr_global_struct - > time + 0.05 ;
vars - > think = currentfunc ;
pr_global_struct - > cycle_wrapped = false ;
if ( startFrame < = endFrame )
{ // Increment
if ( vars - > frame < startFrame | | vars - > frame > endFrame )
{
vars - > frame = startFrame ;
return ;
}
vars - > frame + + ;
if ( vars - > frame > endFrame )
{
pr_global_struct - > cycle_wrapped = true ;
vars - > frame = startFrame ;
}
return ;
}
// Decrement
if ( vars - > frame > startFrame | | vars - > frame < endFrame )
{
vars - > frame = startFrame ;
return ;
}
vars - > frame - - ;
if ( vars - > frame < endFrame )
{
pr_global_struct - > cycle_wrapped = true ;
vars - > frame = startFrame ;
}
}
void CWStateOp ( progfuncs_t * prinst , float startFrame , float endFrame , func_t currentfunc )
{
2005-03-28 00:11:59 +00:00
entvars_t * vars = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) - > v ;
2004-08-23 00:15:46 +00:00
vars - > nextthink = pr_global_struct - > time + 0.05 ;
vars - > think = currentfunc ;
pr_global_struct - > cycle_wrapped = false ;
if ( startFrame < = endFrame )
{ // Increment
if ( vars - > weaponframe < startFrame | | vars - > weaponframe > endFrame )
{
vars - > weaponframe = startFrame ;
return ;
}
vars - > weaponframe + + ;
if ( vars - > weaponframe > endFrame )
{
pr_global_struct - > cycle_wrapped = true ;
vars - > weaponframe = startFrame ;
}
return ;
}
// Decrement
if ( vars - > weaponframe > startFrame | | vars - > weaponframe < endFrame )
{
vars - > weaponframe = startFrame ;
return ;
}
vars - > weaponframe - - ;
if ( vars - > weaponframe < endFrame )
{
pr_global_struct - > cycle_wrapped = true ;
vars - > weaponframe = startFrame ;
}
}
void ThinkTimeOp ( progfuncs_t * prinst , edict_t * ed , float var )
{
2005-03-28 00:11:59 +00:00
entvars_t * vars = ed - > v ;
2004-08-23 00:15:46 +00:00
# ifdef PARANOID
NUM_FOR_EDICT ( ed ) ; // Make sure it's in range
# endif
vars - > nextthink = pr_global_struct - > time + var ;
}
//int QCEditor (char *filename, int line, int nump, char **parms);
void QC_Clear ( void ) ;
builtin_t pr_builtin [ ] ;
extern int pr_numbuiltins ;
//a little loop so we can keep track of used mem
2005-04-19 21:09:29 +00:00
void * VARGS PR_CB_Malloc ( int size )
2004-08-23 00:15:46 +00:00
{
return BZ_Malloc ( size ) ; //Z_TagMalloc (size, 100);
}
2005-04-19 21:09:29 +00:00
void VARGS PR_CB_Free ( void * mem )
2004-08-23 00:15:46 +00:00
{
BZ_Free ( mem ) ;
}
void PF_break ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) ;
int QCLibEditor ( char * filename , int line , int nump , char * * parms ) ;
int QCEditor ( char * filename , int line , int nump , char * * parms )
{
2004-09-08 05:09:33 +00:00
# ifdef TEXTEDITOR
static char oldfuncname [ 64 ] ;
if ( ! parms )
return QCLibEditor ( filename , line , nump , parms ) ;
else
{
2004-11-17 17:52:18 +00:00
if ( ! nump & & ! strncmp ( oldfuncname , * parms , sizeof ( oldfuncname ) ) )
2004-09-08 05:09:33 +00:00
{
2004-11-17 17:52:18 +00:00
Con_Printf ( " Executing %s: %s \n " , * parms , filename ) ;
2004-09-08 05:09:33 +00:00
Q_strncpyz ( oldfuncname , * parms , sizeof ( oldfuncname ) ) ;
}
return line ;
}
# else
2004-08-23 00:15:46 +00:00
int i ;
char buffer [ 8192 ] ;
char * r ;
FILE * f ;
2004-09-08 05:09:33 +00:00
2004-08-23 00:15:46 +00:00
if ( line = = - 1 )
return - 1 ;
COM_FOpenFile ( filename , & f ) ;
if ( ! f )
Con_Printf ( " %s - %i \n " , filename , line ) ;
else
{
for ( i = 0 ; i < line ; i + + )
{
fgets ( buffer , sizeof ( buffer ) , f ) ;
}
if ( ( r = strchr ( buffer , ' \r ' ) ) )
{ r [ 0 ] = ' \n ' ; r [ 1 ] = ' \0 ' ; }
Con_Printf ( " %s " , buffer ) ;
fclose ( f ) ;
}
//PF_break(NULL);
return line ;
2004-09-08 05:09:33 +00:00
# endif
2004-08-23 00:15:46 +00:00
}
void Q_SetProgsParms ( qboolean forcompiler )
{
progstype = PROG_NONE ;
svprogparms . progsversion = PROGSTRUCT_VERSION ;
svprogparms . ReadFile = COM_LoadStackFile ; //char *(*ReadFile) (char *fname, void *buffer, int *len);
svprogparms . FileSize = COM_FileSize ; //int (*FileSize) (char *fname); //-1 if file does not exist
svprogparms . WriteFile = QC_WriteFile ; //bool (*WriteFile) (char *name, void *data, int len);
svprogparms . printf = ( void * ) Con_Printf ; //Con_Printf;//void (*printf) (char *, ...);
svprogparms . Sys_Error = Sys_Error ;
svprogparms . Abort = SV_Error ;
2005-03-28 00:11:59 +00:00
svprogparms . edictsize = sizeof ( edict_t ) ;
2004-08-23 00:15:46 +00:00
svprogparms . entspawn = ED_Spawned ; //void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
svprogparms . entcanfree = ED_CanFree ; //bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
svprogparms . stateop = StateOp ; //void (*stateop) (float var, func_t func);
svprogparms . cstateop = CStateOp ;
svprogparms . cwstateop = CWStateOp ;
svprogparms . thinktimeop = ThinkTimeOp ;
//used when loading a game
svprogparms . builtinsfor = NULL ; //builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
svprogparms . loadcompleate = NULL ; //void (*loadcompleate) (int edictsize); //notification to reset any pointers.
2005-04-19 21:09:29 +00:00
svprogparms . memalloc = PR_CB_Malloc ; //void *(*memalloc) (int size); //small string allocation malloced and freed randomly
svprogparms . memfree = PR_CB_Free ; //void (*memfree) (void * mem);
2004-08-23 00:15:46 +00:00
svprogparms . globalbuiltins = pr_builtin ; //builtin_t *globalbuiltins; //these are available to all progs
svprogparms . numglobalbuiltins = pr_numbuiltins ;
svprogparms . autocompile = PR_COMPILECHANGED ; //enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile;
svprogparms . gametime = & sv . time ;
svprogparms . sv_edicts = & sv . edicts ;
svprogparms . sv_num_edicts = & sv . num_edicts ;
svprogparms . useeditor = QCEditor ; //void (*useeditor) (char *filename, int line, int nump, char **parms);
if ( ! svprogfuncs )
{
svprogfuncs = InitProgs ( & svprogparms ) ;
PR_RegisterSVBuiltins ( ) ;
}
PR_ClearThreads ( ) ;
2005-04-16 16:21:27 +00:00
PR_fclose_progs ( svprogfuncs ) ;
2004-08-23 00:15:46 +00:00
// svs.numprogs = 0;
}
void PR_Deinit ( void )
{
PR_ClearThreads ( ) ;
if ( svprogfuncs )
2005-04-18 17:12:18 +00:00
{
PR_fclose_progs ( svprogfuncs ) ;
2004-08-23 00:15:46 +00:00
CloseProgs ( svprogfuncs ) ;
2005-04-18 17:12:18 +00:00
}
2004-08-23 00:15:46 +00:00
svprogfuncs = NULL ;
}
2004-10-13 06:37:44 +00:00
# define QW_PROGHEADER_CRC 54730
# define NQ_PROGHEADER_CRC 5927
2005-05-08 17:03:19 +00:00
# define PREREL_PROGHEADER_CRC 26940 //prerelease
2004-10-13 06:37:44 +00:00
# define H2_PROGHEADER_CRC 38488 //basic hexen2
# define H2MP_PROGHEADER_CRC 26905 //hexen2 mission pack uses slightly different defs... *sigh*...
2004-08-23 00:15:46 +00:00
void PR_LoadGlabalStruct ( void )
{
2004-08-31 23:58:18 +00:00
static float dimension_send_default ;
2004-08-23 00:15:46 +00:00
int i ;
int * v ;
nqglobalvars_t * pr_globals = pr_nqglobal_struct ;
2004-11-17 17:52:18 +00:00
# define globalfloat(need,name) ((nqglobalvars_t*)pr_nqglobal_struct)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n");
# define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
2005-05-15 18:49:04 +00:00
# define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
2004-11-17 17:52:18 +00:00
# define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n");
# define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
2004-08-23 00:15:46 +00:00
// globalint(pad);
globalint ( true , self ) ; //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
globalint ( true , other ) ;
globalint ( true , world ) ;
globalfloat ( true , time ) ;
globalfloat ( true , frametime ) ;
globalint ( false , newmis ) ; //not always in nq.
2005-05-08 17:03:19 +00:00
globalfloat ( false , force_retouch ) ;
2004-08-23 00:15:46 +00:00
globalstring ( true , mapname ) ;
globalfloat ( false , deathmatch ) ;
globalfloat ( false , coop ) ;
globalfloat ( false , teamplay ) ;
globalfloat ( true , serverflags ) ;
globalfloat ( true , total_secrets ) ;
globalfloat ( true , total_monsters ) ;
globalfloat ( true , found_secrets ) ;
globalfloat ( true , killed_monsters ) ;
globalfloat ( true , parm1 ) ;
globalfloat ( true , parm2 ) ;
globalfloat ( true , parm3 ) ;
globalfloat ( true , parm4 ) ;
globalfloat ( true , parm5 ) ;
globalfloat ( true , parm6 ) ;
globalfloat ( true , parm7 ) ;
globalfloat ( true , parm8 ) ;
globalfloat ( true , parm9 ) ;
globalfloat ( true , parm10 ) ;
globalfloat ( true , parm11 ) ;
globalfloat ( true , parm12 ) ;
globalfloat ( true , parm13 ) ;
globalfloat ( true , parm14 ) ;
globalfloat ( true , parm15 ) ;
globalfloat ( true , parm16 ) ;
globalvec ( true , v_forward ) ;
globalvec ( true , v_up ) ;
globalvec ( true , v_right ) ;
globalfloat ( true , trace_allsolid ) ;
globalfloat ( true , trace_startsolid ) ;
globalfloat ( true , trace_fraction ) ;
globalvec ( true , trace_endpos ) ;
globalvec ( true , trace_plane_normal ) ;
globalfloat ( true , trace_plane_dist ) ;
globalint ( true , trace_ent ) ;
globalfloat ( true , trace_inopen ) ;
globalfloat ( true , trace_inwater ) ;
2005-05-08 17:03:19 +00:00
globalint ( false , msg_entity ) ;
2004-08-23 00:15:46 +00:00
globalfunc ( false , main ) ;
globalfunc ( true , StartFrame ) ;
globalfunc ( true , PlayerPreThink ) ;
globalfunc ( true , PlayerPostThink ) ;
globalfunc ( true , ClientKill ) ;
globalfunc ( true , ClientConnect ) ;
globalfunc ( true , PutClientInServer ) ;
globalfunc ( true , ClientDisconnect ) ;
globalfunc ( false , SetNewParms ) ;
globalfunc ( false , SetChangeParms ) ;
globalfloat ( false , cycle_wrapped ) ;
2004-08-31 23:58:18 +00:00
globalfloat ( false , dimension_send ) ;
2004-10-13 06:37:44 +00:00
memset ( & evalc_idealpitch , 0 , sizeof ( evalc_idealpitch ) ) ;
memset ( & evalc_pitch_speed , 0 , sizeof ( evalc_pitch_speed ) ) ;
2004-08-31 23:58:18 +00:00
if ( ! ( ( nqglobalvars_t * ) pr_globals ) - > dimension_send )
2004-10-13 06:37:44 +00:00
{ //make sure dimension send is always a valid pointer.
2004-08-31 23:58:18 +00:00
( ( nqglobalvars_t * ) pr_globals ) - > dimension_send = & dimension_send_default ;
}
2004-09-04 17:52:32 +00:00
pr_global_struct - > dimension_send = 255 ;
2004-08-23 00:15:46 +00:00
pr_teamfield = 0 ;
SpectatorConnect = PR_FindFunction ( svprogfuncs , " SpectatorConnect " , PR_ANY ) ;
SpectatorDisconnect = PR_FindFunction ( svprogfuncs , " SpectatorDisconnect " , PR_ANY ) ;
SpectatorThink = PR_FindFunction ( svprogfuncs , " SpectatorThink " , PR_ANY ) ;
for ( i = 0 ; i < MAX_CL_STATS ; i + + )
{
getplayerstat [ i ] = PR_FindFunction ( svprogfuncs , va ( " SetPlayerStat%i " , i ) , PR_ANY ) ;
getplayerstati [ i ] = PR_FindFunction ( svprogfuncs , va ( " SetPlayerStat%ii " , i ) , PR_ANY ) ;
}
SV_ParseClientCommand = PR_FindFunction ( svprogfuncs , " SV_ParseClientCommand " , PR_ANY ) ;
2004-10-13 06:37:44 +00:00
UserInfo_Changed = PR_FindFunction ( svprogfuncs , " UserInfo_Changed " , PR_ANY ) ;
localinfoChanged = PR_FindFunction ( svprogfuncs , " localinfoChanged " , PR_ANY ) ;
ChatMessage = PR_FindFunction ( svprogfuncs , " ChatMessage " , PR_ANY ) ;
mod_UserCmd = PR_FindFunction ( svprogfuncs , " UserCmd " , PR_ANY ) ;
mod_ConsoleCmd = PR_FindFunction ( svprogfuncs , " ConsoleCmd " , PR_ANY ) ;
2004-08-23 00:15:46 +00:00
2004-11-20 00:55:29 +00:00
if ( pr_no_playerphysics . value )
SV_PlayerPhysicsQC = 0 ;
else
SV_PlayerPhysicsQC = PR_FindFunction ( svprogfuncs , " SV_PlayerPhysics " , PR_ANY ) ;
2004-08-23 00:15:46 +00:00
EndFrameQC = PR_FindFunction ( svprogfuncs , " EndFrame " , PR_ANY ) ;
v = ( int * ) PR_globals ( svprogfuncs , PR_CURRENT ) ;
QC_AddSharedVar ( svprogfuncs , ( int * ) ( ( nqglobalvars_t * ) pr_nqglobal_struct ) - > self - v , 1 ) ;
QC_AddSharedVar ( svprogfuncs , ( int * ) ( ( nqglobalvars_t * ) pr_nqglobal_struct ) - > other - v , 1 ) ;
QC_AddSharedVar ( svprogfuncs , ( int * ) ( ( nqglobalvars_t * ) pr_nqglobal_struct ) - > time - v , 1 ) ;
pr_items2 = ! ! PR_FindGlobal ( svprogfuncs , " items2 " , 0 ) ;
PR_CleanLogText_Init ( ) ;
2004-10-13 06:37:44 +00:00
SV_ClearQCStats ( ) ;
if ( progstype = = PROG_H2 )
{
SV_QCStat ( ev_float , " level " , STAT_H2_LEVEL ) ;
SV_QCStat ( ev_float , " intelligence " , STAT_H2_INTELLIGENCE ) ;
SV_QCStat ( ev_float , " wisdom " , STAT_H2_WISDOM ) ;
SV_QCStat ( ev_float , " strength " , STAT_H2_STRENGTH ) ;
SV_QCStat ( ev_float , " dexterity " , STAT_H2_DEXTERITY ) ;
SV_QCStat ( ev_float , " bluemana " , STAT_H2_BLUEMANA ) ;
SV_QCStat ( ev_float , " greenmana " , STAT_H2_GREENMANA ) ;
SV_QCStat ( ev_float , " experience " , STAT_H2_EXPERIENCE ) ;
SV_QCStat ( ev_float , " cnt_torch " , STAT_H2_CNT_TORCH ) ;
SV_QCStat ( ev_float , " cnt_h_boost " , STAT_H2_CNT_H_BOOST ) ;
SV_QCStat ( ev_float , " cnt_sh_boost " , STAT_H2_CNT_SH_BOOST ) ;
SV_QCStat ( ev_float , " cnt_mana_boost " , STAT_H2_CNT_MANA_BOOST ) ;
SV_QCStat ( ev_float , " cnt_teleport " , STAT_H2_CNT_TELEPORT ) ;
SV_QCStat ( ev_float , " cnt_tome " , STAT_H2_CNT_TOME ) ;
SV_QCStat ( ev_float , " cnt_summon " , STAT_H2_CNT_SUMMON ) ;
SV_QCStat ( ev_float , " cnt_invisibility " , STAT_H2_CNT_INVISIBILITY ) ;
SV_QCStat ( ev_float , " cnt_glyph " , STAT_H2_CNT_GLYPH ) ;
SV_QCStat ( ev_float , " cnt_haste " , STAT_H2_CNT_HASTE ) ;
SV_QCStat ( ev_float , " cnt_blast " , STAT_H2_CNT_BLAST ) ;
SV_QCStat ( ev_float , " cnt_polymorph " , STAT_H2_CNT_POLYMORPH ) ;
SV_QCStat ( ev_float , " cnt_flight " , STAT_H2_CNT_FLIGHT ) ;
SV_QCStat ( ev_float , " cnt_cubeofforce " , STAT_H2_CNT_CUBEOFFORCE ) ;
SV_QCStat ( ev_float , " cnt_invincibility " , STAT_H2_CNT_INVINCIBILITY ) ;
SV_QCStat ( ev_float , " artifact_active " , STAT_H2_ARTIFACT_ACTIVE ) ;
SV_QCStat ( ev_float , " artifact_low " , STAT_H2_ARTIFACT_LOW ) ;
SV_QCStat ( ev_float , " artifact_low " , STAT_H2_ARTIFACT_LOW ) ;
SV_QCStat ( ev_float , " movetype " , STAT_H2_MOVETYPE ) ;
SV_QCStat ( ev_entity , " cameramode " , STAT_H2_CAMERAMODE ) ;
SV_QCStat ( ev_float , " hasted " , STAT_H2_HASTED ) ;
SV_QCStat ( ev_float , " inventory " , STAT_H2_INVENTORY ) ;
SV_QCStat ( ev_float , " rings_active " , STAT_H2_RINGS_ACTIVE ) ;
SV_QCStat ( ev_float , " rings_low " , STAT_H2_RINGS_LOW ) ;
SV_QCStat ( ev_float , " armor_amulet " , STAT_H2_AMULET ) ;
SV_QCStat ( ev_float , " armor_bracer " , STAT_H2_BRACER ) ;
SV_QCStat ( ev_float , " armor_breastplate " , STAT_H2_BREASTPLATE ) ;
SV_QCStat ( ev_float , " armor_helmet " , STAT_H2_HELMET ) ;
SV_QCStat ( ev_float , " ring_flight " , STAT_H2_FLIGHT_T ) ;
SV_QCStat ( ev_float , " ring_water " , STAT_H2_WATER_T ) ;
SV_QCStat ( ev_float , " ring_turning " , STAT_H2_TURNING_T ) ;
SV_QCStat ( ev_float , " ring_regeneration " , STAT_H2_REGEN_T ) ;
SV_QCStat ( ev_string , " puzzle_inv1 " , STAT_H2_PUZZLE1A ) ;
SV_QCStat ( ev_string , " puzzle_inv2 " , STAT_H2_PUZZLE2A ) ;
SV_QCStat ( ev_string , " puzzle_inv3 " , STAT_H2_PUZZLE3A ) ;
SV_QCStat ( ev_string , " puzzle_inv4 " , STAT_H2_PUZZLE4A ) ;
SV_QCStat ( ev_string , " puzzle_inv5 " , STAT_H2_PUZZLE5A ) ;
SV_QCStat ( ev_string , " puzzle_inv6 " , STAT_H2_PUZZLE6A ) ;
SV_QCStat ( ev_string , " puzzle_inv7 " , STAT_H2_PUZZLE7A ) ;
SV_QCStat ( ev_string , " puzzle_inv8 " , STAT_H2_PUZZLE8A ) ;
SV_QCStat ( ev_float , " max_health " , STAT_H2_MAXHEALTH ) ;
SV_QCStat ( ev_float , " max_mana " , STAT_H2_MAXMANA ) ;
SV_QCStat ( ev_float , " flags " , STAT_H2_FLAGS ) ;
}
2004-08-23 00:15:46 +00:00
}
progsnum_t AddProgs ( char * name )
{
float fl ;
func_t f ;
globalvars_t * pr_globals ;
progsnum_t num ;
int i ;
for ( i = 0 ; i < svs . numprogs ; i + + )
{
if ( ! strcmp ( svs . progsnames [ i ] , name ) )
{
return svs . progsnum [ i ] ;
}
}
if ( svs . numprogs > = MAX_PROGS )
return - 1 ;
svprogparms . autocompile = PR_COMPILECHANGED ;
if ( progstype = = PROG_QW )
2004-10-13 06:37:44 +00:00
num = PR_LoadProgs ( svprogfuncs , name , QW_PROGHEADER_CRC , NULL , 0 ) ;
2004-08-23 00:15:46 +00:00
else if ( progstype = = PROG_NQ )
num = PR_LoadProgs ( svprogfuncs , name , NQ_PROGHEADER_CRC , NULL , 0 ) ;
else if ( progstype = = PROG_UNKNOWN )
num = PR_LoadProgs ( svprogfuncs , name , 0 , NULL , 0 ) ;
else //if (progstype == PROG_NONE)
{
progstype = PROG_QW ;
2004-10-13 06:37:44 +00:00
num = PR_LoadProgs ( svprogfuncs , name , QW_PROGHEADER_CRC , NULL , 0 ) ;
2004-08-23 00:15:46 +00:00
if ( num = = - 1 )
{
svprogparms . autocompile = PR_NOCOMPILE ;
progstype = PROG_NQ ;
num = PR_LoadProgs ( svprogfuncs , name , NQ_PROGHEADER_CRC , NULL , 0 ) ;
if ( num = = - 1 )
{
progstype = PROG_H2 ;
num = PR_LoadProgs ( svprogfuncs , name , H2_PROGHEADER_CRC , NULL , 0 ) ;
if ( num = = - 1 ) //don't commit if bad.
num = PR_LoadProgs ( svprogfuncs , name , H2MP_PROGHEADER_CRC , NULL , 0 ) ;
if ( num = = - 1 ) //don't commit if bad.
{
2005-05-08 17:03:19 +00:00
progstype = PROG_PREREL ;
num = PR_LoadProgs ( svprogfuncs , name , PREREL_PROGHEADER_CRC , NULL , 0 ) ;
if ( num = = - 1 )
2004-08-23 00:15:46 +00:00
{
2005-05-08 17:03:19 +00:00
progstype = PROG_UNKNOWN ;
num = PR_LoadProgs ( svprogfuncs , name , 0 , NULL , 0 ) ;
if ( num = = - 1 ) //don't commit if bad.
{
progstype = PROG_NONE ;
}
else
Cvar_Set ( & qc_nonetaccess , " 1 " ) ; //just in case
2004-08-23 00:15:46 +00:00
}
}
}
}
if ( num ! = - 1 )
{
PR_LoadGlabalStruct ( ) ;
switch ( progstype )
{
case PROG_QW :
Con_Printf ( " Using QW progs \n " ) ;
break ;
case PROG_NQ :
Con_Printf ( " Using NQ progs \n " ) ;
break ;
case PROG_H2 :
Con_Printf ( " Using H2 progs \n " ) ;
break ;
2005-05-08 17:03:19 +00:00
case PROG_PREREL :
Con_Printf ( " Using prerelease progs \n " ) ;
break ;
2004-08-23 00:15:46 +00:00
default :
Con_Printf ( " Using unknown progs, assuming NQ \n " ) ;
break ;
}
}
}
svprogparms . autocompile = PR_COMPILECHANGED ;
if ( num = = - 1 )
{
Con_Printf ( " Failed to load %s \n " , name ) ;
return - 1 ;
}
Con_Printf ( " Loaded %s \n " , name ) ;
if ( ! svs . numprogs )
2005-05-20 03:32:53 +00:00
{
PF_InitTempStrings ( svprogfuncs ) ;
2004-08-23 00:15:46 +00:00
PR_ResetBuiltins ( progstype ) ;
2005-05-20 03:32:53 +00:00
}
2004-08-23 00:15:46 +00:00
2004-11-17 17:52:18 +00:00
if ( ( f = PR_FindFunction ( svprogfuncs , " VersionChat " , num ) ) )
2004-08-23 00:15:46 +00:00
{
pr_globals = PR_globals ( svprogfuncs , num ) ;
G_FLOAT ( OFS_PARM0 ) = VERSION ;
PR_ExecuteProgram ( svprogfuncs , f ) ;
fl = G_FLOAT ( OFS_RETURN ) ;
if ( fl < 0 )
2004-11-17 17:52:18 +00:00
SV_Error ( " PR_LoadProgs: progs.dat is not compatable with EXE version " ) ;
2004-08-23 00:15:46 +00:00
else if ( ( int ) ( fl * 1000 ) ! = ( int ) ( VERSION * 1000 ) )
Con_DPrintf ( " Warning: Progs may not be fully compatable \n (%4.2f != %4.2f) \n " , fl , VERSION ) ;
}
2004-11-17 17:52:18 +00:00
if ( ( f = PR_FindFunction ( svprogfuncs , " FTE_init " , num ) ) )
2004-08-23 00:15:46 +00:00
{
pr_globals = PR_globals ( svprogfuncs , num ) ;
G_FLOAT ( OFS_PARM0 ) = VERSION ;
PR_ExecuteProgram ( svprogfuncs , f ) ;
}
2004-11-17 17:52:18 +00:00
2004-08-23 00:15:46 +00:00
strcpy ( svs . progsnames [ svs . numprogs ] , name ) ;
svs . progsnum [ svs . numprogs ] = num ;
svs . numprogs + + ;
return num ;
}
void PR_Decompile_f ( void )
{
if ( ! svprogfuncs )
{
Con_Printf ( " Progs not running, you need to start a server first \n " ) ;
return ;
}
if ( Cmd_Argc ( ) = = 1 )
svprogfuncs - > Decompile ( svprogfuncs , " qwprogs.dat " ) ;
else
svprogfuncs - > Decompile ( svprogfuncs , Cmd_Argv ( 1 ) ) ;
}
void PR_Compile_f ( void )
{
int argc = 3 ;
double time = Sys_DoubleTime ( ) ;
2004-11-17 17:52:18 +00:00
char * argv [ 64 ] = { " " , " -srcfile " , " qwprogs.src " } ;
2004-08-23 00:15:46 +00:00
2004-11-17 17:52:18 +00:00
if ( Cmd_Argc ( ) = = 2 )
2004-08-23 00:15:46 +00:00
argv [ 2 ] = Cmd_Argv ( 1 ) ;
2004-11-17 17:52:18 +00:00
else if ( Cmd_Argc ( ) > 2 )
{
for ( argc = 0 ; argc < Cmd_Argc ( ) ; argc + + )
argv [ argc ] = Cmd_Argv ( argc ) ;
}
2004-08-23 00:15:46 +00:00
if ( ! svprogfuncs )
Q_SetProgsParms ( true ) ;
2005-02-28 07:16:19 +00:00
if ( PR_StartCompile ( svprogfuncs , argc , argv ) )
while ( PR_ContinueCompile ( svprogfuncs ) ) ;
2004-08-23 00:15:46 +00:00
time = Sys_DoubleTime ( ) - time ;
Con_TPrintf ( STL_COMPILEROVER , time ) ;
}
void PR_ApplyCompilation_f ( void )
{
edict_t * ent ;
char * s ;
int len , i ;
if ( sv . state < ss_active )
{
Con_Printf ( " Can't apply: Server isn't running or is still loading \n " ) ;
return ;
}
Con_Printf ( " Saving state \n " ) ;
s = PR_SaveEnts ( svprogfuncs , NULL , & len , 1 ) ;
2005-03-28 00:11:59 +00:00
PR_Configure ( svprogfuncs , - 1 , MAX_PROGS ) ;
2004-08-23 00:15:46 +00:00
PR_RegisterFields ( ) ;
PR_InitEnts ( svprogfuncs , sv . max_edicts ) ;
pr_edict_size = svprogfuncs - > load_ents ( svprogfuncs , s , 0 ) ;
PR_LoadGlabalStruct ( ) ;
pr_global_struct - > time = sv . time ;
SV_ClearWorld ( ) ;
for ( i = 0 ; i < sv . allocated_client_slots ; i + + )
{
ent = EDICT_NUM ( svprogfuncs , i + 1 ) ;
svs . clients [ i ] . edict = ent ;
}
ent = sv . edicts ;
for ( i = 0 ; i < sv . num_edicts ; i + + )
{
ent = EDICT_NUM ( svprogfuncs , i ) ;
if ( ent - > isfree )
continue ;
SV_LinkEdict ( ent , false ) ; // force retouch even for stationary
}
svprogfuncs - > parms - > memfree ( s ) ;
}
void PR_BreakPoint_f ( void )
{
int wasset ;
int isset ;
char * filename = Cmd_Argv ( 1 ) ;
int line = atoi ( Cmd_Argv ( 2 ) ) ;
if ( ! svprogfuncs )
{
Con_Printf ( " Start the server first \n " ) ;
return ;
}
wasset = svprogfuncs - > ToggleBreak ( svprogfuncs , filename , line , 3 ) ;
isset = svprogfuncs - > ToggleBreak ( svprogfuncs , filename , line , 2 ) ;
if ( wasset = = isset )
Con_Printf ( " Breakpoint was not valid \n " ) ;
else if ( isset )
Con_Printf ( " Breakpoint has been set \n " ) ;
else
Con_Printf ( " Breakpoint has been cleared \n " ) ;
}
2005-05-17 02:36:54 +00:00
# ifdef _DEBUG
void QCLibTest ( void )
{
2005-05-26 12:55:34 +00:00
int size = 1024 * 1024 * 8 ;
char * buffer = BZ_Malloc ( size ) ;
svprogfuncs - > save_ents ( svprogfuncs , buffer , & size , 3 ) ;
COM_WriteFile ( " ssqccore.txt " , buffer , size ) ;
BZ_Free ( buffer ) ;
2005-05-17 02:36:54 +00:00
PR_TestForWierdness ( svprogfuncs ) ;
}
# endif
2004-08-23 00:15:46 +00:00
typedef char char32 [ 32 ] ;
char32 sv_addonname [ MAXADDONS ] ;
void PR_Init ( void )
{
int i ;
Cmd_AddCommand ( " breakpoint " , PR_BreakPoint_f ) ;
Cmd_AddCommand ( " decompile " , PR_Decompile_f ) ;
Cmd_AddCommand ( " compile " , PR_Compile_f ) ;
Cmd_AddCommand ( " applycompile " , PR_ApplyCompilation_f ) ;
2005-05-17 02:36:54 +00:00
# ifdef _DEBUG
Cmd_AddCommand ( " svtestprogs " , QCLibTest ) ;
# endif
2004-08-23 00:15:46 +00:00
Cvar_Register ( & pr_maxedicts , cvargroup_progs ) ;
Cvar_Register ( & pr_imitatemvdsv , cvargroup_progs ) ;
Cvar_Register ( & pr_fixbrokenqccarrays , cvargroup_progs ) ;
2004-11-20 00:55:29 +00:00
Cvar_Register ( & pr_no_playerphysics , cvargroup_progs ) ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < MAXADDONS ; i + + )
{
sprintf ( sv_addonname [ i ] , " addon%i " , i ) ;
sv_addon [ i ] . name = sv_addonname [ i ] ;
sv_addon [ i ] . string = " " ;
sv_addon [ i ] . flags = CVAR_NOTFROMSERVER ;
Cvar_Register ( & sv_addon [ i ] , cvargroup_progs ) ;
}
Cvar_Register ( & nomonsters , cvargroup_progs ) ;
Cvar_Register ( & gamecfg , cvargroup_progs ) ;
Cvar_Register ( & scratch1 , cvargroup_progs ) ;
Cvar_Register ( & scratch2 , cvargroup_progs ) ;
Cvar_Register ( & scratch3 , cvargroup_progs ) ;
Cvar_Register ( & scratch4 , cvargroup_progs ) ;
Cvar_Register ( & savedgamecfg , cvargroup_progs ) ;
Cvar_Register ( & saved1 , cvargroup_progs ) ;
Cvar_Register ( & saved2 , cvargroup_progs ) ;
Cvar_Register ( & saved3 , cvargroup_progs ) ;
Cvar_Register ( & saved4 , cvargroup_progs ) ;
Cvar_Register ( & temp1 , cvargroup_progs ) ;
Cvar_Register ( & noexit , cvargroup_progs ) ;
Cvar_Register ( & progs , cvargroup_progs ) ;
2004-08-31 23:58:18 +00:00
Cvar_Register ( & pr_compatabilitytest , cvargroup_progs ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & qc_nonetaccess , cvargroup_progs ) ;
Cvar_Register ( & pr_overridebuiltins , cvargroup_progs ) ;
}
void Q_InitProgs ( void )
{
int i , i2 ;
func_t f , f2 ;
globalvars_t * pr_globals ;
static char addons [ 2048 ] ;
char * as , * a ;
int num = 0 ;
progsnum_t prnum , oldprnum ;
int d1 , d2 ;
QC_Clear ( ) ;
Q_SetProgsParms ( false ) ;
// load progs to get entity field count
2005-03-28 00:11:59 +00:00
PR_Configure ( svprogfuncs , - 1 , MAX_PROGS ) ;
2004-08-23 00:15:46 +00:00
PR_RegisterFields ( ) ;
num = svs . numprogs ;
svs . numprogs = 0 ;
d1 = COM_FDepthFile ( " progs.dat " , true ) ;
d2 = COM_FDepthFile ( " qwprogs.dat " , true ) ;
if ( d1 < d2 ) //progs.dat is closer to the gamedir
strcpy ( addons , " progs.dat " ) ;
else if ( d1 > d2 ) //qwprogs.dat is closest
{
strcpy ( addons , " qwprogs.dat " ) ;
d1 = d2 ;
}
//both are an equal distance - same path.
else if ( deathmatch . value & & ! COM_CheckParm ( " -game " ) ) //if deathmatch, default to qw
{
strcpy ( addons , " qwprogs.dat " ) ;
d1 = d2 ;
}
else //single player/coop is better done with nq.
{
strcpy ( addons , " progs.dat " ) ;
}
//if progs cvar is left blank and a q2 map is loaded, the server will use the q2 game dll.
//if you do set a value here, q2 dll is not used.
//hexen2 - maplist contains a list of maps that we need to use an alternate progs.dat for.
d2 = COM_FDepthFile ( " maplist.txt " , true ) ;
if ( d2 < = d1 ) //Use it if the maplist.txt file is within a more or equal important gamedir.
{
int j , maps ;
char * f ;
f = COM_LoadTempFile ( " maplist.txt " ) ;
f = COM_Parse ( f ) ;
maps = atoi ( com_token ) ;
for ( j = 0 ; j < maps ; j + + )
{
f = COM_Parse ( f ) ;
if ( ! Q_strcasecmp ( sv . name , com_token ) )
{
f = COM_Parse ( f ) ;
strcpy ( addons , com_token ) ;
break ;
}
f = strchr ( f , ' \n ' ) ; //skip to the end of the line.
}
}
if ( * progs . string & & strlen ( progs . string ) < 64 & & * progs . string ! = ' * ' ) //a * is a special case to not load a q2 dll.
{
Q_strncpyz ( addons , progs . string , MAX_QPATH ) ;
COM_DefaultExtension ( addons , " .dat " ) ;
}
oldprnum = AddProgs ( addons ) ;
if ( oldprnum < 0 & & strcmp ( addons , " qwprogs.dat " ) )
{
# ifndef SERVERONLY
if ( SCR_UpdateScreen )
SCR_UpdateScreen ( ) ;
# endif
oldprnum = AddProgs ( " qwprogs.dat " ) ;
}
if ( oldprnum < 0 & & strcmp ( addons , " progs.dat " ) )
{
# ifndef SERVERONLY
if ( SCR_UpdateScreen )
SCR_UpdateScreen ( ) ;
# endif
oldprnum = AddProgs ( " progs.dat " ) ;
}
if ( oldprnum < 0 )
2004-11-17 17:52:18 +00:00
SV_Error ( " Couldn't open or compile progs \n " ) ;
2004-08-23 00:15:46 +00:00
f = PR_FindFunction ( svprogfuncs , " AddAddonProgs " , oldprnum ) ;
/* if (num)
{
//restore progs
for ( i = 1 ; i < num ; i + + )
{
if ( f )
{
pr_globals = PR_globals ( PR_CURRENT ) ;
G_SETSTRING ( OFS_PARM0 , svs . progsnames [ i ] ) ;
PR_ExecuteProgram ( f ) ;
}
else
{
prnum = AddProgs ( svs . progsnames [ i ] ) ;
f2 = PR_FindFunction ( " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( f2 ) ;
}
oldprnum = prnum ;
}
}
}
*/
//additional (always) progs
as = NULL ;
a = COM_LoadStackFile ( " mod.gam " , addons , 2048 ) ;
if ( a )
{
as = strstr ( a , " extraqwprogs= " ) ;
if ( as )
{
for ( a = as + 13 ; * a ; a + + )
{
if ( * a < ' ' )
{
* a = ' \0 ' ;
break ;
}
}
a = ( as + = 13 ) ;
}
}
if ( as )
{
while ( * a )
{
if ( * a = = ' ; ' )
{
* a = ' \0 ' ;
for ( i = 0 ; i < svs . numprogs ; i + + ) //don't add if already added
{
if ( ! strcmp ( svs . progsnames [ i ] , as ) )
break ;
}
if ( i = = svs . numprogs )
{
if ( f )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-09-20 23:25:38 +00:00
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , as ) ;
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( svprogfuncs , f ) ;
}
else
{
prnum = AddProgs ( as ) ;
if ( prnum > = 0 )
{
f2 = PR_FindFunction ( svprogfuncs , " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( svprogfuncs , f2 ) ;
}
oldprnum = prnum ;
}
}
}
* a = ' ; ' ;
as = a + 1 ;
}
a + + ;
}
}
if ( COM_FDepthFile ( " fteadd.dat " , true ) ! = 0x7fffffff )
{
prnum = AddProgs ( " fteadd.dat " ) ;
if ( prnum > = 0 )
{
f2 = PR_FindFunction ( svprogfuncs , " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( svprogfuncs , f2 ) ;
}
oldprnum = prnum ;
}
}
prnum = 0 ;
2004-09-14 21:41:59 +00:00
switch ( sv . worldmodel - > fromgame ) //spawn functions for - spawn funcs still come from the first progs found.
2004-08-23 00:15:46 +00:00
{
case fg_quake2 :
if ( COM_FDepthFile ( " q2bsp.dat " , true ) ! = 0x7fffffff )
prnum = AddProgs ( " q2bsp.dat " ) ;
break ;
case fg_quake3 :
if ( COM_FDepthFile ( " q3bsp.dat " , true ) ! = 0x7fffffff )
prnum = AddProgs ( " q3bsp.dat " ) ;
else if ( COM_FDepthFile ( " q2bsp.dat " , true ) ! = 0x7fffffff ) //fallback
prnum = AddProgs ( " q2bsp.dat " ) ;
break ;
case fg_doom :
if ( COM_FDepthFile ( " doombsp.dat " , true ) ! = 0x7fffffff )
prnum = AddProgs ( " doombsp.dat " ) ;
break ;
case fg_halflife :
if ( COM_FDepthFile ( " hlbsp.dat " , true ) ! = 0x7fffffff )
prnum = AddProgs ( " hlbsp.dat " ) ;
break ;
2004-09-14 21:41:59 +00:00
default :
break ;
2004-08-23 00:15:46 +00:00
}
if ( prnum > = 0 )
{
f2 = PR_FindFunction ( svprogfuncs , " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( svprogfuncs , f2 ) ;
}
oldprnum = prnum ;
}
//progs depended on by maps.
a = as = COM_LoadStackFile ( va ( " maps/%s.inf " , sv . name ) , addons , 2048 ) ;
if ( a )
{
as = strstr ( a , " qwprogs= " ) ;
if ( as )
{
for ( a = as + 11 ; * a ; a + + )
{
if ( * a < ' ' )
{
* a = ' \0 ' ;
break ;
}
}
a = ( as + = 11 ) ;
}
}
if ( as )
{
while ( * a )
{
if ( * a = = ' ; ' )
{
* a = ' \0 ' ;
for ( i = 0 ; i < svs . numprogs ; i + + ) //don't add if already added
{
if ( ! strcmp ( svs . progsnames [ i ] , as ) )
break ;
}
if ( i = = svs . numprogs )
{
if ( f )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-09-20 23:25:38 +00:00
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , as ) ;
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( svprogfuncs , f ) ;
}
else
{
prnum = AddProgs ( as ) ;
if ( prnum > = 0 )
{
f2 = PR_FindFunction ( svprogfuncs , " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( svprogfuncs , f2 ) ;
}
oldprnum = prnum ;
}
}
}
* a = ' ; ' ;
as = a + 1 ;
}
a + + ;
}
}
//add any addons specified
for ( i2 = 0 ; i2 < MAXADDONS ; i2 + + )
{
if ( * sv_addon [ i2 ] . string )
{
for ( i = 0 ; i < svs . numprogs ; i + + ) //don't add if already added
{
if ( ! strcmp ( svs . progsnames [ i ] , sv_addon [ i2 ] . string ) )
break ;
}
if ( i = = svs . numprogs ) //Not added yet. Add it.
{
if ( f )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-09-20 23:25:38 +00:00
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , as ) ;
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( svprogfuncs , f ) ;
}
else
{
prnum = AddProgs ( sv_addon [ i2 ] . string ) ;
if ( prnum > = 0 )
{
f2 = PR_FindFunction ( svprogfuncs , " init " , prnum ) ;
if ( f2 )
{
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
G_PROG ( OFS_PARM0 ) = oldprnum ;
PR_ExecuteProgram ( svprogfuncs , f2 ) ;
}
oldprnum = prnum ;
}
}
}
}
}
sv . max_edicts = pr_maxedicts . value ;
pr_edict_size = PR_InitEnts ( svprogfuncs , sv . max_edicts ) ;
}
qboolean PR_QCChat ( char * text , int say_type )
{
globalvars_t * pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-10-13 06:37:44 +00:00
if ( ! ChatMessage | | pr_imitatemvdsv . value > = 0 )
2004-08-23 00:15:46 +00:00
return false ;
2004-09-20 23:25:38 +00:00
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , text ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_PARM1 ) = say_type ;
PR_ExecuteProgram ( svprogfuncs , ChatMessage ) ;
if ( G_FLOAT ( OFS_RETURN ) )
return true ;
return false ;
}
2004-12-15 19:58:07 +00:00
qboolean PR_KrimzonParseCommand ( char * s )
2004-08-23 00:15:46 +00:00
{
globalvars_t * pr_globals ;
2004-12-15 19:58:07 +00:00
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
if ( ge )
2004-12-15 19:58:07 +00:00
return false ;
2004-08-23 00:15:46 +00:00
# endif
if ( SV_ParseClientCommand )
2004-12-15 19:58:07 +00:00
{ //the QC is expected to send it back to use via a builtin.
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , s ) ;
PR_ExecuteProgram ( svprogfuncs , SV_ParseClientCommand ) ;
2004-12-05 11:51:44 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
2004-12-15 19:58:07 +00:00
return false ;
}
qboolean PR_UserCmd ( char * s )
{
globalvars_t * pr_globals ;
# ifdef Q2SERVER
if ( ge )
2004-08-23 00:15:46 +00:00
{
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( RD_CLIENT , host_client - > language ) ;
2004-12-15 19:58:07 +00:00
ge - > ClientCommand ( host_client - > q2edict ) ;
SV_EndRedirect ( ) ;
return true ; //the dll will convert it to chat.
}
# endif
2004-12-19 04:37:42 +00:00
if ( SV_ParseClientCommand )
{ //the QC is expected to send it back to use via a builtin.
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , s ) ;
PR_ExecuteProgram ( svprogfuncs , SV_ParseClientCommand ) ;
return true ;
}
2004-12-15 19:58:07 +00:00
if ( mod_UserCmd & & pr_imitatemvdsv . value > = 0 )
{ //we didn't recognise it. see if the mod does.
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , s ) ;
PR_ExecuteProgram ( svprogfuncs , mod_UserCmd ) ;
2004-12-15 19:58:07 +00:00
return ! ! G_FLOAT ( OFS_RETURN ) ;
2004-08-23 00:15:46 +00:00
}
return false ;
}
qboolean PR_ConsoleCmd ( void )
{
globalvars_t * pr_globals ;
extern redirect_t sv_redirected ;
2005-03-12 23:40:42 +00:00
if ( Cmd_ExecLevel < cmd_gamecodelevel . value )
return false ;
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
if ( ge )
2004-08-27 00:42:51 +00:00
{ //server command
if ( ! strcmp ( Cmd_Argv ( 0 ) , " sv " ) )
{
ge - > ServerCommand ( ) ;
return true ;
}
return false ;
2004-08-23 00:15:46 +00:00
}
# endif
2005-03-12 23:40:42 +00:00
if ( svprogfuncs )
2004-08-23 00:15:46 +00:00
{
2005-03-12 23:40:42 +00:00
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
if ( mod_ConsoleCmd & & pr_imitatemvdsv . value > = 0 )
2004-08-23 00:15:46 +00:00
{
2005-03-12 23:40:42 +00:00
if ( sv_redirected ! = RD_OBLIVION )
{
pr_global_struct - > time = sv . time ;
2005-03-28 00:11:59 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv . edicts ) ;
2005-03-12 23:40:42 +00:00
}
PR_ExecuteProgram ( svprogfuncs , mod_ConsoleCmd ) ;
return ( int ) G_FLOAT ( OFS_RETURN ) ;
2004-08-23 00:15:46 +00:00
}
}
return false ;
}
void PR_ClientUserInfoChanged ( char * name , char * oldivalue , char * newvalue )
{
2004-10-13 06:37:44 +00:00
if ( UserInfo_Changed & & pr_imitatemvdsv . value > = 0 )
2004-08-23 00:15:46 +00:00
{
globalvars_t * pr_globals ;
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , name ) ;
G_INT ( OFS_PARM1 ) = ( int ) PR_SetString ( svprogfuncs , oldivalue ) ;
G_INT ( OFS_PARM2 ) = ( int ) PR_SetString ( svprogfuncs , newvalue ) ;
PR_ExecuteProgram ( svprogfuncs , UserInfo_Changed ) ;
}
}
void PR_LocalInfoChanged ( char * name , char * oldivalue , char * newvalue )
{
2004-10-13 06:37:44 +00:00
if ( localinfoChanged & & sv . state & & pr_imitatemvdsv . value > = 0 )
2004-08-23 00:15:46 +00:00
{
globalvars_t * pr_globals ;
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv . edicts ) ;
G_INT ( OFS_PARM0 ) = ( int ) PR_SetString ( svprogfuncs , name ) ;
G_INT ( OFS_PARM1 ) = ( int ) PR_SetString ( svprogfuncs , oldivalue ) ;
G_INT ( OFS_PARM2 ) = ( int ) PR_SetString ( svprogfuncs , newvalue ) ;
PR_ExecuteProgram ( svprogfuncs , localinfoChanged ) ;
}
}
2004-11-17 17:52:18 +00:00
void VARGS PR_BIError ( progfuncs_t * progfuncs , char * format , . . . )
2004-08-23 00:15:46 +00:00
{
va_list argptr ;
static char string [ 2048 ] ;
va_start ( argptr , format ) ;
_vsnprintf ( string , sizeof ( string ) - 1 , format , argptr ) ;
va_end ( argptr ) ;
if ( developer . value )
{
2004-11-21 07:31:26 +00:00
globalvars_t * pr_globals = PR_globals ( progfuncs , PR_CURRENT ) ;
2004-08-23 00:15:46 +00:00
Con_Printf ( " %s \n " , string ) ;
2004-11-21 07:31:26 +00:00
* progfuncs - > pr_trace = 1 ;
2004-08-23 00:15:46 +00:00
G_INT ( OFS_RETURN ) = 0 ; //just in case it was a float and should be an ent...
G_INT ( OFS_RETURN + 1 ) = 0 ;
G_INT ( OFS_RETURN + 2 ) = 0 ;
}
else
2004-11-21 07:31:26 +00:00
{
2005-02-28 07:16:19 +00:00
PR_StackTrace ( progfuncs ) ;
PR_AbortStack ( progfuncs ) ;
2004-11-21 07:31:26 +00:00
progfuncs - > parms - > Abort ( " %s " , string ) ;
}
2004-08-23 00:15:46 +00:00
}
void QC_Clear ( void )
{
}
int prnumforfile ;
int PR_SizeOfFile ( char * filename )
{
extern int com_filesize ;
// int size;
if ( ! svprogfuncs )
return - 1 ;
prnumforfile = svs . numprogs - 1 ;
while ( prnumforfile > = 0 )
{
2005-05-17 02:36:54 +00:00
if ( ( qbyte * ) svprogfuncs - > filefromprogs ( svprogfuncs , prnumforfile , filename , & com_filesize , NULL ) = = ( qbyte * ) - 1 )
2004-08-23 00:15:46 +00:00
return com_filesize ;
prnumforfile - - ;
}
return - 1 ;
}
qbyte * PR_OpenFile ( char * filename , qbyte * buffer )
{
return svprogfuncs - > filefromprogs ( svprogfuncs , prnumforfile , filename , NULL , buffer ) ;
}
char * Translate ( char * message ) ;
char * PF_VarString ( progfuncs_t * prinst , int first , globalvars_t * pr_globals )
{
int i ;
static char buffer [ 2 ] [ 4096 ] ;
static int bufnum ;
char * s , * out ;
out = buffer [ ( bufnum + + ) & 1 ] ;
out [ 0 ] = 0 ;
for ( i = first ; i < * prinst - > callargc ; i + + )
{
s = PR_GetStringOfs ( prinst , OFS_PARM0 + i * 3 ) ;
if ( s )
{
strcat ( out , Translate ( s ) ) ;
//#ifdef PARANOID
if ( strlen ( out ) + 1 > = sizeof ( buffer [ 0 ] ) )
Sys_Error ( " VarString (builtin call ending with strings) exceeded maximum string length of %i chars " , sizeof ( buffer [ 0 ] ) ) ;
//#endif
}
}
return out ;
}
//#define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e))
2005-05-15 18:49:04 +00:00
# define RETURN_SSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it.
# define RETURN_TSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //temp (static but cycle buffers?)
# define RETURN_CSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //semi-permanant. (hash tables?)
2005-05-17 02:36:54 +00:00
# define RETURN_PSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_NewString(prinst, s, 0)) //permanant
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BUILT - IN FUNCTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
int externcallsdepth ;
void PR_MoveParms ( int progs1 , int progs2 ) ; //from 2 to 1
void PF_externcall ( progfuncs_t * prinst , globalvars_t * pr_globals ) //this func calls a function in annother progs (by name)
{
int progsnum ;
char * funcname ;
int i ;
2005-05-17 02:36:54 +00:00
string_t failedst = G_INT ( OFS_PARM1 ) ;
2004-08-23 00:15:46 +00:00
func_t f ;
progsnum = G_PROG ( OFS_PARM0 ) ;
funcname = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
f = PR_FindFunction ( prinst , funcname , progsnum ) ;
if ( f )
{
for ( i = OFS_PARM0 ; i < OFS_PARM5 ; i + = 3 )
VectorCopy ( G_VECTOR ( i + ( 2 * 3 ) ) , G_VECTOR ( i ) ) ;
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) + + ; //continue debugging
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( prinst , f ) ;
}
else if ( ! f )
{
f = PR_FindFunction ( prinst , " MissingFunc " , progsnum ) ;
if ( ! f )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Couldn't find function %s " , funcname ) ;
2004-08-23 00:15:46 +00:00
return ;
}
for ( i = OFS_PARM0 ; i < OFS_PARM6 ; i + = 3 )
VectorCopy ( G_VECTOR ( i + ( 1 * 3 ) ) , G_VECTOR ( i ) ) ;
2005-05-17 02:36:54 +00:00
G_INT ( OFS_PARM0 ) = failedst ;
2004-08-23 00:15:46 +00:00
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) + + ; //continue debugging
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( prinst , f ) ;
}
}
//this func calls a function in annother progs
//it works in the same way as the above func, except that it calls by reference to a function, as opposed to by it's name
//used for entity function variables - not actually needed anymore
void PF_externrefcall ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
int progsnum ;
func_t f ;
progsnum = G_PROG ( OFS_PARM0 ) ;
f = G_INT ( OFS_PARM1 ) ;
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) + + ; //continue debugging.
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( prinst , f ) ;
}
float PR_LoadAditionalProgs ( char * s ) ;
void PF_addprogs ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
char * s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
if ( ! s | | ! * s )
{
G_PROG ( OFS_RETURN ) = - 1 ;
return ;
}
G_PROG ( OFS_RETURN ) = AddProgs ( s ) ;
}
void PF_externvalue ( progfuncs_t * prinst , globalvars_t * pr_globals ) //return a value in annother progs
{
int n = G_PROG ( OFS_PARM0 ) ;
char * varname = PF_VarString ( prinst , 1 , pr_globals ) ;
eval_t * var ;
var = svprogfuncs - > FindGlobal ( prinst , varname , n ) ;
if ( var )
G_INT ( OFS_RETURN ) = var - > _int ;
else
G_INT ( OFS_RETURN ) = 0 ;
}
void PF_externset ( progfuncs_t * prinst , globalvars_t * pr_globals ) //set a value in annother progs
{
int n = G_PROG ( OFS_PARM0 ) ;
int v = G_INT ( OFS_PARM1 ) ;
char * varname = PF_VarString ( prinst , 2 , pr_globals ) ;
eval_t * var ;
if ( n < 0 )
{
for ( n = 0 ; n < svs . numprogs ; n + + )
{
var = svprogfuncs - > FindGlobal ( prinst , varname , svs . progsnum [ n ] ) ;
if ( var )
var - > _int = v ;
}
return ;
}
var = svprogfuncs - > FindGlobal ( prinst , varname , n ) ;
if ( var )
var - > _int = v ;
}
void PF_instr ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
char * sub ;
char * s1 ;
char * s2 ;
s1 = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
s2 = PF_VarString ( prinst , 1 , pr_globals ) ;
if ( ! s1 | | ! s2 )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Null string in \" instr \" \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
sub = strstr ( s1 , s2 ) ;
if ( sub = = NULL )
2005-02-28 07:16:19 +00:00
G_INT ( OFS_RETURN ) = 0 ;
2004-08-23 00:15:46 +00:00
else
RETURN_SSTRING ( sub ) ; //last as long as the origional string
}
/*
char * PF_VarString ( int first )
{
int i ;
static char out [ 256 ] ;
out [ 0 ] = 0 ;
for ( i = first ; i < pr_argc ; i + + )
{
strcat ( out , G_STRING ( ( OFS_PARM0 + i * 3 ) ) ) ;
}
return out ;
}
*/
/*
= = = = = = = = = = = = = = = = =
PF_errror
This is a TERMINAL error , which will kill off the entire server .
Dumps self .
error ( value )
= = = = = = = = = = = = = = = = =
*/
void PF_break ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) ;
void PF_error ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
s = PF_VarString ( prinst , 0 , pr_globals ) ;
/* Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
ed = PROG_TO_EDICT ( pr_global_struct - > self ) ;
ED_Print ( ed ) ;
*/
2005-02-28 07:16:19 +00:00
PR_StackTrace ( prinst ) ;
2004-11-21 07:31:26 +00:00
2004-11-17 17:52:18 +00:00
Con_Printf ( " %s \n " , s ) ;
2004-08-23 00:15:46 +00:00
if ( developer . value )
{
// SV_Error ("Program error: %s", s);
PF_break ( prinst , pr_globals ) ;
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = 2 ;
2004-08-23 00:15:46 +00:00
}
else
2004-11-21 07:31:26 +00:00
{
2005-02-28 07:16:19 +00:00
PR_AbortStack ( prinst ) ;
2004-11-21 07:31:26 +00:00
PR_BIError ( prinst , " Program error: %s " , s ) ;
}
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
PF_objerror
Dumps out self , then an error message . The program is aborted and self is
removed , but the level can continue .
objerror ( value )
= = = = = = = = = = = = = = = = =
*/
2005-02-28 07:16:19 +00:00
static void PF_objerror ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
char * s ;
edict_t * ed ;
s = PF_VarString ( prinst , 0 , pr_globals ) ;
/* Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
*/ ed = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
/* ED_Print (ed);
*/
ED_Print ( prinst , ed ) ;
Con_Printf ( " %s " , s ) ;
if ( developer . value )
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = 2 ;
2004-08-23 00:15:46 +00:00
else
{
2004-11-21 07:31:26 +00:00
ED_Free ( prinst , ed ) ;
prinst - > AbortStack ( prinst ) ;
2004-08-23 00:15:46 +00:00
2004-11-23 00:35:37 +00:00
PR_BIError ( prinst , " Program error: %s " , s ) ;
2004-08-23 00:15:46 +00:00
if ( sv . time > 10 )
Cbuf_AddText ( " restart \n " , RESTRICT_LOCAL ) ;
}
}
/*
= = = = = = = = = = = = = =
PF_makevectors
Writes new values for v_forward , v_up , and v_right based on angles
makevectors ( vector )
= = = = = = = = = = = = = =
*/
2005-01-16 00:59:48 +00:00
static void PF_makevectors ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
AngleVectors ( G_VECTOR ( OFS_PARM0 ) , P_VEC ( v_forward ) , P_VEC ( v_right ) , P_VEC ( v_up ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_setorigin
This is the only valid way to move an object without using the physics of the world ( setting velocity and waiting ) . Directly changing origin will not set internal links correctly , so clipping would be messed up . This should be called when an object is spawned , and then only if it is teleported .
setorigin ( entity , origin )
= = = = = = = = = = = = = = = = =
*/
void PF_setorigin ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e ;
float * org ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
org = G_VECTOR ( OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
VectorCopy ( org , e - > v - > origin ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( e , false ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_setsize
the size box is rotated by the current angle
setsize ( entity , minvector , maxvector )
= = = = = = = = = = = = = = = = =
*/
void PF_setsize ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e ;
float * min , * max ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
if ( e - > isfree )
{
Con_TPrintf ( STL_EDICTWASFREE , " setsize " ) ;
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = 1 ;
2004-08-23 00:15:46 +00:00
return ;
}
min = G_VECTOR ( OFS_PARM1 ) ;
max = G_VECTOR ( OFS_PARM2 ) ;
2005-03-28 00:11:59 +00:00
VectorCopy ( min , e - > v - > mins ) ;
VectorCopy ( max , e - > v - > maxs ) ;
VectorSubtract ( max , min , e - > v - > size ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( e , false ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_setmodel
setmodel ( entity , model )
Also sets size , mins , and maxs for inline bmodels
= = = = = = = = = = = = = = = = =
*/
void PF_setmodel ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e ;
char * m ;
int i ;
model_t * mod ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
m = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
// check to see if model was properly precached
if ( ! m | | ! * m )
i = 0 ;
else
{
for ( i = 1 ; * sv . model_precache [ i ] ; i + + )
2004-09-04 17:52:32 +00:00
{
2004-08-23 00:15:46 +00:00
if ( ! strcmp ( sv . model_precache [ i ] , m ) )
{
m = sv . model_precache [ i ] ;
break ;
}
2004-09-04 17:52:32 +00:00
}
2005-05-17 02:36:54 +00:00
if ( i = = MAX_MODELS | | ! sv . model_precache [ i ] )
2004-09-04 17:52:32 +00:00
{
if ( i ! = MAX_MODELS & & sv . state = = ss_loading )
{
2005-05-17 02:36:54 +00:00
sv . model_precache [ i ] = PR_AddString ( prinst , m , 0 ) ;
2004-09-04 17:52:32 +00:00
if ( ! strcmp ( m + strlen ( m ) - 4 , " .bsp " ) )
sv . models [ i ] = Mod_FindName ( sv . model_precache [ i ] ) ;
Con_Printf ( " WARNING: SV_ModelIndex: model %s not precached " , m ) ;
}
else
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " no precache: %s \n " , m ) ;
2004-09-04 17:52:32 +00:00
return ;
}
2004-08-23 00:15:46 +00:00
}
}
2005-01-16 00:59:48 +00:00
2005-03-28 00:11:59 +00:00
e - > v - > model = PR_SetString ( prinst , sv . model_precache [ i ] ) ;
e - > v - > modelindex = i ;
2004-08-23 00:15:46 +00:00
// if it is an inline model, get the size information for it
if ( m [ 0 ] = = ' * ' | | ( * m & & progstype = = PROG_H2 ) )
{
mod = Mod_ForName ( m , true ) ;
2005-04-26 16:04:12 +00:00
if ( mod )
{
VectorCopy ( mod - > mins , e - > v - > mins ) ;
VectorCopy ( mod - > maxs , e - > v - > maxs ) ;
VectorSubtract ( mod - > maxs , mod - > mins , e - > v - > size ) ;
SV_LinkEdict ( e , false ) ;
}
2004-08-23 00:15:46 +00:00
return ;
}
if ( progstype = = PROG_H2 )
{
2005-03-28 00:11:59 +00:00
e - > v - > mins [ 0 ] = 0 ;
e - > v - > mins [ 1 ] = 0 ;
e - > v - > mins [ 2 ] = 0 ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
e - > v - > maxs [ 0 ] = 0 ;
e - > v - > maxs [ 1 ] = 0 ;
e - > v - > maxs [ 2 ] = 0 ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
VectorSubtract ( e - > v - > maxs , e - > v - > mins , e - > v - > size ) ;
2004-08-23 00:15:46 +00:00
}
else
{
if ( progstype ! = PROG_QW )
2004-09-22 15:27:05 +00:00
{ //also sets size.
//nq dedicated servers load bsps and mdls
//qw dedicated servers only load bsps (better)
mod = sv . models [ i ] ;
2004-08-23 00:15:46 +00:00
if ( mod )
{
2005-04-16 16:21:27 +00:00
mod = Mod_ForName ( m , false ) ;
2005-04-26 16:04:12 +00:00
if ( mod )
{
VectorCopy ( mod - > mins , e - > v - > mins ) ;
VectorCopy ( mod - > maxs , e - > v - > maxs ) ;
VectorSubtract ( mod - > maxs , mod - > mins , e - > v - > size ) ;
SV_LinkEdict ( e , false ) ;
}
2004-08-23 00:15:46 +00:00
}
else
{
2004-09-22 15:27:05 +00:00
//it's an interesting fact that nq pretended that it's models were all +/- 16 (causing culling issues).
//seing as dedicated servers don't want to load mdls,
//imitate the behaviour of setting the size (which nq can only have as +/- 16)
//hell, this works with quakerally so why not use it.
2005-03-28 00:11:59 +00:00
e - > v - > mins [ 0 ] =
e - > v - > mins [ 1 ] =
e - > v - > mins [ 2 ] = - 16 ;
e - > v - > maxs [ 0 ] =
e - > v - > maxs [ 1 ] =
e - > v - > maxs [ 2 ] = 16 ;
VectorSubtract ( e - > v - > maxs , e - > v - > mins , e - > v - > size ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( e , false ) ;
}
}
else
{
if ( sv . models [ i ] )
{
2005-04-16 16:21:27 +00:00
mod = Mod_ForName ( m , false ) ;
2005-04-26 16:04:12 +00:00
if ( mod )
{
VectorCopy ( mod - > mins , e - > v - > mins ) ;
VectorCopy ( mod - > maxs , e - > v - > maxs ) ;
VectorSubtract ( mod - > maxs , mod - > mins , e - > v - > size ) ;
SV_LinkEdict ( e , false ) ;
}
2004-08-23 00:15:46 +00:00
}
2004-09-22 15:27:05 +00:00
//qw was fixed - it never sets the size of an alias model.
2004-08-23 00:15:46 +00:00
}
}
}
void PF_set_puzzle_model ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{ //qc/hc lacks string manipulation.
char * shortname ;
char fullname [ MAX_QPATH ] ;
shortname = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
_snprintf ( fullname , sizeof ( fullname ) - 1 , " models/puzzle/%s.mdl " , shortname ) ;
G_INT ( OFS_PARM1 ) = ( int ) ( fullname - prinst - > stringtable ) ;
PF_setmodel ( prinst , pr_globals ) ;
G_INT ( OFS_PARM1 ) = ( int ) ( shortname - prinst - > stringtable ) ; //piece of mind.
}
/*
= = = = = = = = = = = = = = = = =
PF_bprint
broadcast print to everyone on server
bprint ( value )
= = = = = = = = = = = = = = = = =
*/
void PF_bprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int level ;
if ( sv . demofile )
return ;
2005-05-08 17:03:19 +00:00
if ( progstype ! = PROG_QW )
2004-08-23 00:15:46 +00:00
{
level = PRINT_HIGH ;
s = PF_VarString ( prinst , 0 , pr_globals ) ;
}
else
{
level = G_FLOAT ( OFS_PARM0 ) ;
s = PF_VarString ( prinst , 1 , pr_globals ) ;
}
SV_BroadcastPrintf ( level , " %s " , s ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_sprint
single print to a specific client
sprint ( clientent , value )
= = = = = = = = = = = = = = = = =
*/
void PF_sprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
client_t * client ;
int entnum ;
int level ;
if ( sv . demofile )
return ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
level = PRINT_HIGH ;
s = PF_VarString ( prinst , 1 , pr_globals ) ;
}
else
{
level = G_FLOAT ( OFS_PARM1 ) ;
s = PF_VarString ( prinst , 2 , pr_globals ) ;
}
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
{
Con_TPrintf ( STL_BADSPRINT ) ;
return ;
}
client = & svs . clients [ entnum - 1 ] ;
SV_ClientPrintf ( client , level , " %s " , s ) ;
}
2005-04-16 16:21:27 +00:00
//When a client is backbuffered, it's generally not a brilliant plan to send a bazillion stuffcmds. You have been warned.
//This handy function will let the mod know when it shouldn't send more. (use instead of a timer, and you'll never get clients overflowing. yay.)
void PF_isbackbuffered ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int entnum ;
client_t * client ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
{
Con_Printf ( " PF_isbackbuffered: Not a client \n " ) ;
return ;
}
client = & svs . clients [ entnum - 1 ] ;
G_FLOAT ( OFS_RETURN ) = client - > num_backbuf > 0 ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_centerprint
single print to a specific client
centerprint ( clientent , value )
= = = = = = = = = = = = = = = = =
*/
void PF_centerprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int entnum ;
client_t * cl , * sp ;
if ( sv . demofile )
return ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
s = PF_VarString ( prinst , 1 , pr_globals ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
{
Con_TPrintf ( STL_BADSPRINT ) ;
return ;
}
cl = & svs . clients [ entnum - 1 ] ;
if ( cl - > controller )
{ //this is a slave client.
//find the right number and send.
int pnum = 0 ;
for ( sp = cl - > controller ; sp ; sp = sp - > controlled )
{
if ( sp = = cl )
break ;
pnum + + ;
}
sp = cl - > controller ;
ClientReliableWrite_Begin ( sp , svc_choosesplitclient , 4 + strlen ( s ) ) ;
ClientReliableWrite_Byte ( sp , pnum ) ;
ClientReliableWrite_Byte ( sp , svc_centerprint ) ;
ClientReliableWrite_String ( sp , s ) ;
}
else
{
ClientReliableWrite_Begin ( cl , svc_centerprint , 2 + strlen ( s ) ) ;
ClientReliableWrite_String ( cl , s ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
PF_normalize
vector normalize ( vector )
= = = = = = = = = = = = = = = = =
*/
void PF_normalize ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * value1 ;
vec3_t newvalue ;
float new ;
value1 = G_VECTOR ( OFS_PARM0 ) ;
new = value1 [ 0 ] * value1 [ 0 ] + value1 [ 1 ] * value1 [ 1 ] + value1 [ 2 ] * value1 [ 2 ] ;
new = sqrt ( new ) ;
if ( new = = 0 )
newvalue [ 0 ] = newvalue [ 1 ] = newvalue [ 2 ] = 0 ;
else
{
new = 1 / new ;
newvalue [ 0 ] = value1 [ 0 ] * new ;
newvalue [ 1 ] = value1 [ 1 ] * new ;
newvalue [ 2 ] = value1 [ 2 ] * new ;
}
VectorCopy ( newvalue , G_VECTOR ( OFS_RETURN ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_vlen
scalar vlen ( vector )
= = = = = = = = = = = = = = = = =
*/
void PF_vlen ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * value1 ;
float new ;
value1 = G_VECTOR ( OFS_PARM0 ) ;
new = value1 [ 0 ] * value1 [ 0 ] + value1 [ 1 ] * value1 [ 1 ] + value1 [ 2 ] * value1 [ 2 ] ;
new = sqrt ( new ) ;
G_FLOAT ( OFS_RETURN ) = new ;
}
/*
= = = = = = = = = = = = = = = = =
PF_vlen
scalar vhlen ( vector )
= = = = = = = = = = = = = = = = =
*/
void PF_vhlen ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * value1 ;
float new ;
value1 = G_VECTOR ( OFS_PARM0 ) ;
new = value1 [ 0 ] * value1 [ 0 ] + value1 [ 1 ] * value1 [ 1 ] ;
new = sqrt ( new ) ;
G_FLOAT ( OFS_RETURN ) = new ;
}
/*
= = = = = = = = = = = = = = = = =
PF_vectoyaw
float vectoyaw ( vector )
= = = = = = = = = = = = = = = = =
*/
void PF_vectoyaw ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * value1 ;
float yaw ;
value1 = G_VECTOR ( OFS_PARM0 ) ;
if ( value1 [ 1 ] = = 0 & & value1 [ 0 ] = = 0 )
yaw = 0 ;
else
{
yaw = ( int ) ( atan2 ( value1 [ 1 ] , value1 [ 0 ] ) * 180 / M_PI ) ;
if ( yaw < 0 )
yaw + = 360 ;
}
G_FLOAT ( OFS_RETURN ) = yaw ;
}
void PF_anglemod ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float v = G_FLOAT ( OFS_PARM0 ) ;
while ( v > = 360 )
v = v - 360 ;
while ( v < 0 )
v = v + 360 ;
G_FLOAT ( OFS_RETURN ) = v ;
}
/*
= = = = = = = = = = = = = = = = =
PF_vectoangles
vector vectoangles ( vector )
= = = = = = = = = = = = = = = = =
*/
void PF_vectoangles ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * value1 ;
float forward ;
float yaw , pitch ;
value1 = G_VECTOR ( OFS_PARM0 ) ;
if ( value1 [ 1 ] = = 0 & & value1 [ 0 ] = = 0 )
{
yaw = 0 ;
if ( value1 [ 2 ] > 0 )
pitch = 90 ;
else
pitch = 270 ;
}
else
{
yaw = ( int ) ( atan2 ( value1 [ 1 ] , value1 [ 0 ] ) * 180 / M_PI ) ;
if ( yaw < 0 )
yaw + = 360 ;
forward = sqrt ( value1 [ 0 ] * value1 [ 0 ] + value1 [ 1 ] * value1 [ 1 ] ) ;
pitch = ( int ) ( atan2 ( value1 [ 2 ] , forward ) * 180 / M_PI ) ;
if ( pitch < 0 )
pitch + = 360 ;
}
G_FLOAT ( OFS_RETURN + 0 ) = pitch ;
G_FLOAT ( OFS_RETURN + 1 ) = yaw ;
G_FLOAT ( OFS_RETURN + 2 ) = 0 ;
}
static long predictablerandx = 1 ;
void predictablesrand ( unsigned int x )
{
predictablerandx = x ;
}
int predictablerandgetseed ( void )
{
return predictablerandx ;
}
int predictablerand ( void )
{
return ( ( ( predictablerandx = predictablerandx * 1103515245 + 12345 ) > > 16 ) & 077777 ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_Random
Returns a number from 0 < = num < 1
random ( )
= = = = = = = = = = = = = = = = =
*/
void PF_random ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float num ;
if ( svs . demorecording | | svs . demoplayback )
num = ( predictablerand ( ) & 0x7fff ) / ( ( float ) 0x7fff ) ;
else
num = ( rand ( ) & 0x7fff ) / ( ( float ) 0x7fff ) ;
G_FLOAT ( OFS_RETURN ) = num ;
}
/*
= = = = = = = = = = = = = = = = =
PF_particle
particle ( origin , color , count )
= = = = = = = = = = = = = = = = =
*/
void PF_particle ( progfuncs_t * prinst , globalvars_t * pr_globals ) //I said it was for compatability only.
{
float * org , * dir ;
float color ;
float count ;
int i , v ;
org = G_VECTOR ( OFS_PARM0 ) ;
dir = G_VECTOR ( OFS_PARM1 ) ;
color = G_FLOAT ( OFS_PARM2 ) ;
count = G_FLOAT ( OFS_PARM3 ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_particle ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 2 ] ) ;
for ( i = 0 ; i < 3 ; i + + )
{
v = dir [ i ] * 16 ;
if ( v > 127 )
v = 127 ;
else if ( v < - 128 )
v = - 128 ;
MSG_WriteChar ( & sv . nqmulticast , v ) ;
}
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqmulticast , count * 20 ) ;
MSG_WriteByte ( & sv . nqmulticast , color ) ;
2004-08-23 00:15:46 +00:00
# endif
2004-08-31 23:58:18 +00:00
//for qw users (and not fte)
2004-10-14 13:08:09 +00:00
/* if (*prinst->callargc >= 5)
{
PARM4 = te_
optional PARM5 = count
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , TE_BLOOD ) ;
MSG_WriteByte ( & sv . multicast , count < 10 ? 1 : ( count + 10 ) / 20 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , 0 , PEXT_HEXEN2 ) ;
}
else
*/
if ( color = = 73 )
2004-08-23 00:15:46 +00:00
{
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , TE_BLOOD ) ;
MSG_WriteByte ( & sv . multicast , count < 10 ? 1 : ( count + 10 ) / 20 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , 0 , PEXT_HEXEN2 ) ;
2004-08-23 00:15:46 +00:00
}
else if ( color = = 225 )
{
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , TE_LIGHTNINGBLOOD ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , 0 , PEXT_HEXEN2 ) ;
2004-08-23 00:15:46 +00:00
}
2004-08-31 23:58:18 +00:00
//now we can start fte svc_particle stuff..
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & sv . multicast , svc_particle ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
for ( i = 0 ; i < 3 ; i + + )
{
v = dir [ i ] * 16 ;
if ( v > 127 )
v = 127 ;
else if ( v < - 128 )
v = - 128 ;
MSG_WriteChar ( & sv . multicast , v ) ;
}
MSG_WriteByte ( & sv . multicast , count ) ;
MSG_WriteByte ( & sv . multicast , color ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , PEXT_HEXEN2 , 0 ) ;
2004-08-23 00:15:46 +00:00
}
void PF_te_blood ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
float count ;
float * org , * dir ;
# ifdef NQPROT
int i , v ;
# endif
org = G_VECTOR ( OFS_PARM0 ) ;
dir = G_VECTOR ( OFS_PARM1 ) ;
count = G_FLOAT ( OFS_PARM2 ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_particle ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 2 ] ) ;
for ( i = 0 ; i < 3 ; i + + )
{
v = dir [ i ] * 16 ;
if ( v > 127 )
v = 127 ;
else if ( v < - 128 )
v = - 128 ;
MSG_WriteChar ( & sv . nqmulticast , v ) ;
}
MSG_WriteByte ( & sv . nqmulticast , count ) ;
MSG_WriteByte ( & sv . nqmulticast , 73 ) ;
# endif
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , TE_BLOOD ) ;
MSG_WriteByte ( & sv . multicast , count < 10 ? 1 : ( count + 10 ) / 20 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
SV_Multicast ( org , MULTICAST_PVS ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_particle2 - hexen2
particle ( origin , dmin , dmax , color , effect , count )
= = = = = = = = = = = = = = = = =
*/
void PF_particle2 ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
float * org , * dmin , * dmax ;
float color ;
float count ;
float effect ;
org = G_VECTOR ( OFS_PARM0 ) ;
dmin = G_VECTOR ( OFS_PARM1 ) ;
dmax = G_VECTOR ( OFS_PARM2 ) ;
color = G_FLOAT ( OFS_PARM3 ) ;
effect = G_FLOAT ( OFS_PARM4 ) ;
count = G_FLOAT ( OFS_PARM5 ) ;
MSG_WriteByte ( & sv . multicast , svc_particle2 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmin [ 0 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmin [ 1 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmin [ 2 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmax [ 0 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmax [ 1 ] ) ;
MSG_WriteFloat ( & sv . multicast , dmax [ 2 ] ) ;
MSG_WriteShort ( & sv . multicast , color ) ;
MSG_WriteByte ( & sv . multicast , count ) ;
MSG_WriteByte ( & sv . multicast , effect ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , PEXT_HEXEN2 , 0 ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
PF_particle3 - hexen2
particle ( origin , box , color , effect , count )
= = = = = = = = = = = = = = = = =
*/
void PF_particle3 ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
float * org , * box ;
float color ;
float count ;
float effect ;
org = G_VECTOR ( OFS_PARM0 ) ;
box = G_VECTOR ( OFS_PARM1 ) ;
color = G_FLOAT ( OFS_PARM2 ) ;
effect = G_FLOAT ( OFS_PARM3 ) ;
count = G_FLOAT ( OFS_PARM4 ) ;
MSG_WriteByte ( & sv . multicast , svc_particle3 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
MSG_WriteByte ( & sv . multicast , box [ 0 ] ) ;
MSG_WriteByte ( & sv . multicast , box [ 1 ] ) ;
MSG_WriteByte ( & sv . multicast , box [ 2 ] ) ;
MSG_WriteShort ( & sv . multicast , color ) ;
MSG_WriteByte ( & sv . multicast , count ) ;
MSG_WriteByte ( & sv . multicast , effect ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , PEXT_HEXEN2 , 0 ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
PF_particle4 - hexen2
particle ( origin , radius , color , effect , count )
= = = = = = = = = = = = = = = = =
*/
void PF_particle4 ( progfuncs_t * prinst , globalvars_t * pr_globals )
{
float * org ;
float radius ;
float color ;
float count ;
float effect ;
org = G_VECTOR ( OFS_PARM0 ) ;
radius = G_FLOAT ( OFS_PARM1 ) ;
color = G_FLOAT ( OFS_PARM2 ) ;
effect = G_FLOAT ( OFS_PARM3 ) ;
count = G_FLOAT ( OFS_PARM4 ) ;
MSG_WriteByte ( & sv . multicast , svc_particle4 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
MSG_WriteByte ( & sv . multicast , radius ) ;
MSG_WriteShort ( & sv . multicast , color ) ;
MSG_WriteByte ( & sv . multicast , count ) ;
MSG_WriteByte ( & sv . multicast , effect ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , PEXT_HEXEN2 , 0 ) ;
2004-08-23 00:15:46 +00:00
}
void PF_particleexplosion ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * org ;
int color , radius , counter ;
org = G_VECTOR ( OFS_PARM0 ) ;
color = G_FLOAT ( OFS_PARM1 ) ;
radius = G_FLOAT ( OFS_PARM2 ) ;
counter = G_FLOAT ( OFS_PARM3 ) ;
/*
MSG_WriteByte ( & sv . datagram , svc_particle_explosion ) ;
MSG_WriteCoord ( & sv . datagram , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . datagram , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . datagram , org [ 2 ] ) ;
MSG_WriteShort ( & sv . datagram , color ) ;
MSG_WriteShort ( & sv . datagram , radius ) ;
MSG_WriteShort ( & sv . datagram , counter ) ;
*/
}
/*
= = = = = = = = = = = = = = = = =
PF_ambientsound
= = = = = = = = = = = = = = = = =
*/
void PF_ambientsound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * samp ;
float * pos ;
float vol , attenuation ;
int i , soundnum ;
pos = G_VECTOR ( OFS_PARM0 ) ;
samp = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
vol = G_FLOAT ( OFS_PARM2 ) ;
attenuation = G_FLOAT ( OFS_PARM3 ) ;
// check to see if samp was properly precached
for ( soundnum = 1 ; * sv . sound_precache [ soundnum ] ; soundnum + + )
if ( ! strcmp ( sv . sound_precache [ soundnum ] , samp ) )
break ;
if ( ! * sv . sound_precache [ soundnum ] )
{
Con_TPrintf ( STL_NOPRECACHE , samp ) ;
return ;
}
// add an svc_spawnambient command to the level signon packet
MSG_WriteByte ( & sv . signon , svc_spawnstaticsound ) ;
for ( i = 0 ; i < 3 ; i + + )
MSG_WriteCoord ( & sv . signon , pos [ i ] ) ;
MSG_WriteByte ( & sv . signon , soundnum ) ;
MSG_WriteByte ( & sv . signon , vol * 255 ) ;
MSG_WriteByte ( & sv . signon , attenuation * 64 ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_sound
Each entity can have eight independant sound sources , like voice ,
weapon , feet , etc .
Channel 0 is an auto - allocate channel , the others override anything
allready running on that entity / channel pair .
An attenuation of 0 will play full volume everywhere in the level .
Larger attenuations will drop off .
= = = = = = = = = = = = = = = = =
*/
void PF_sound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * sample ;
int channel ;
edict_t * entity ;
int volume ;
float attenuation ;
entity = G_EDICT ( prinst , OFS_PARM0 ) ;
channel = G_FLOAT ( OFS_PARM1 ) ;
sample = PR_GetStringOfs ( prinst , OFS_PARM2 ) ;
volume = G_FLOAT ( OFS_PARM3 ) * 255 ;
attenuation = G_FLOAT ( OFS_PARM4 ) ;
if ( volume < 0 ) //erm...
return ;
2004-08-31 23:58:18 +00:00
if ( volume > 255 )
volume = 255 ;
2004-08-23 00:15:46 +00:00
SV_StartSound ( entity , channel , sample , volume , attenuation ) ;
}
2004-08-31 23:58:18 +00:00
//an evil one from telejano.
void PF_LocalSound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
# ifndef SERVERONLY
sfx_t * sfx ;
char * s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
float chan = G_FLOAT ( OFS_PARM1 ) ;
float vol = G_FLOAT ( OFS_PARM2 ) ;
2005-03-01 15:36:23 +00:00
if ( ! isDedicated )
{
if ( ( sfx = S_PrecacheSound ( s ) ) )
S_StartSound ( cl . playernum [ 0 ] , chan , sfx , cl . simorg [ 0 ] , vol , 0.0 ) ;
}
2004-08-31 23:58:18 +00:00
# endif
} ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_break
break ( )
= = = = = = = = = = = = = = = = =
*/
void PF_break ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
# ifdef SERVERONLY //new break code
char * s ;
//I would like some sort of network activity here,
//but I don't want to mess up the sequence and stuff
//It should be possible, but would mean that I would
//need to alter the client, or rewrite a bit of the server..
if ( pr_globals )
Con_TPrintf ( STL_BREAKSTATEMENT ) ;
else if ( developer . value ! = 2 )
return ; //non developers cann't step.
for ( ; ; )
{
s = Sys_ConsoleInput ( ) ;
if ( s )
{
if ( ! * s )
break ;
else
Con_Printf ( " %s \n " , svprogfuncs - > EvaluateDebugString ( svprogfuncs , s ) ) ;
}
}
# elif defined(TEXTEDITOR)
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) + + ;
2004-08-23 00:15:46 +00:00
# else //old break code
Con_Printf ( " break statement \n " ) ;
* ( int * ) - 4 = 0 ; // dump to debugger
// PR_RunError ("break statement");
# endif
}
/*
= = = = = = = = = = = = = = = = =
PF_traceline
Used for use tracing and shot targeting
Traces are blocked by bbox and exact bsp entityes , and also slide box entities
if the tryents flag is set .
traceline ( vector1 , vector2 , tryents )
= = = = = = = = = = = = = = = = =
*/
2005-02-28 07:16:19 +00:00
static void PF_traceline ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
float * v1 , * v2 , * mins , * maxs ;
trace_t trace ;
int nomonsters ;
edict_t * ent ;
int savedhull ;
v1 = G_VECTOR ( OFS_PARM0 ) ;
v2 = G_VECTOR ( OFS_PARM1 ) ;
nomonsters = G_FLOAT ( OFS_PARM2 ) ;
ent = G_EDICT ( prinst , OFS_PARM3 ) ;
if ( * svprogfuncs - > callargc = = 6 )
{
mins = G_VECTOR ( OFS_PARM4 ) ;
maxs = G_VECTOR ( OFS_PARM5 ) ;
}
else
{
mins = vec3_origin ;
maxs = vec3_origin ;
}
2005-03-28 00:11:59 +00:00
savedhull = ent - > v - > hull ;
ent - > v - > hull = 0 ;
2004-08-23 00:15:46 +00:00
trace = SV_Move ( v1 , mins , maxs , v2 , nomonsters , ent ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > hull = savedhull ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > trace_allsolid = trace . allsolid ;
pr_global_struct - > trace_startsolid = trace . startsolid ;
pr_global_struct - > trace_fraction = trace . fraction ;
pr_global_struct - > trace_inwater = trace . inwater ;
pr_global_struct - > trace_inopen = trace . inopen ;
// if (trace.fraction != 1)
// VectorMA (trace.endpos, 4, trace.plane.normal, P_VEC(trace_endpos));
// else
VectorCopy ( trace . endpos , P_VEC ( trace_endpos ) ) ;
VectorCopy ( trace . plane . normal , P_VEC ( trace_plane_normal ) ) ;
pr_global_struct - > trace_plane_dist = trace . plane . dist ;
if ( trace . ent )
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , trace . ent ) ;
else
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , sv . edicts ) ;
}
2005-02-28 07:16:19 +00:00
static void PF_traceboxh2 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
float * v1 , * v2 , * mins , * maxs ;
trace_t trace ;
int nomonsters ;
edict_t * ent ;
int savedhull ;
v1 = G_VECTOR ( OFS_PARM0 ) ;
v2 = G_VECTOR ( OFS_PARM1 ) ;
mins = G_VECTOR ( OFS_PARM2 ) ;
maxs = G_VECTOR ( OFS_PARM3 ) ;
nomonsters = G_FLOAT ( OFS_PARM4 ) ;
ent = G_EDICT ( prinst , OFS_PARM5 ) ;
2005-03-28 00:11:59 +00:00
savedhull = ent - > v - > hull ;
ent - > v - > hull = 0 ;
2004-08-23 00:15:46 +00:00
trace = SV_Move ( v1 , mins , maxs , v2 , nomonsters , ent ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > hull = savedhull ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > trace_allsolid = trace . allsolid ;
pr_global_struct - > trace_startsolid = trace . startsolid ;
pr_global_struct - > trace_fraction = trace . fraction ;
pr_global_struct - > trace_inwater = trace . inwater ;
pr_global_struct - > trace_inopen = trace . inopen ;
2005-05-13 10:42:48 +00:00
VectorCopy ( trace . endpos , P_VEC ( trace_endpos ) ) ;
2004-08-23 00:15:46 +00:00
VectorCopy ( trace . plane . normal , P_VEC ( trace_plane_normal ) ) ;
pr_global_struct - > trace_plane_dist = trace . plane . dist ;
if ( trace . ent )
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , trace . ent ) ;
else
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , sv . edicts ) ;
}
2005-02-28 07:16:19 +00:00
static void PF_traceboxdp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
float * v1 , * v2 , * mins , * maxs ;
trace_t trace ;
int nomonsters ;
edict_t * ent ;
int savedhull ;
v1 = G_VECTOR ( OFS_PARM0 ) ;
mins = G_VECTOR ( OFS_PARM1 ) ;
maxs = G_VECTOR ( OFS_PARM2 ) ;
v2 = G_VECTOR ( OFS_PARM3 ) ;
nomonsters = G_FLOAT ( OFS_PARM4 ) ;
ent = G_EDICT ( prinst , OFS_PARM5 ) ;
2005-03-28 00:11:59 +00:00
savedhull = ent - > v - > hull ;
ent - > v - > hull = 0 ;
2004-08-23 00:15:46 +00:00
trace = SV_Move ( v1 , mins , maxs , v2 , nomonsters , ent ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > hull = savedhull ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > trace_allsolid = trace . allsolid ;
pr_global_struct - > trace_startsolid = trace . startsolid ;
pr_global_struct - > trace_fraction = trace . fraction ;
pr_global_struct - > trace_inwater = trace . inwater ;
pr_global_struct - > trace_inopen = trace . inopen ;
// if (trace.fraction != 1)
// VectorMA (trace.endpos, 4, trace.plane.normal, P_VEC(trace_endpos));
// else
VectorCopy ( trace . endpos , P_VEC ( trace_endpos ) ) ;
VectorCopy ( trace . plane . normal , P_VEC ( trace_plane_normal ) ) ;
pr_global_struct - > trace_plane_dist = trace . plane . dist ;
if ( trace . ent )
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , trace . ent ) ;
else
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , sv . edicts ) ;
}
2004-10-13 06:37:44 +00:00
extern trace_t SV_Trace_Toss ( edict_t * ent , edict_t * ignore ) ;
2005-02-28 07:16:19 +00:00
static void PF_TraceToss ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-10-13 06:37:44 +00:00
{
trace_t trace ;
edict_t * ent ;
edict_t * ignore ;
ent = G_EDICT ( prinst , OFS_PARM0 ) ;
if ( ent = = sv . edicts )
Con_DPrintf ( " tracetoss: can not use world entity \n " ) ;
ignore = G_EDICT ( prinst , OFS_PARM1 ) ;
trace = SV_Trace_Toss ( ent , ignore ) ;
pr_global_struct - > trace_allsolid = trace . allsolid ;
pr_global_struct - > trace_startsolid = trace . startsolid ;
pr_global_struct - > trace_fraction = trace . fraction ;
pr_global_struct - > trace_inwater = trace . inwater ;
pr_global_struct - > trace_inopen = trace . inopen ;
VectorCopy ( trace . endpos , pr_global_struct - > V_trace_endpos ) ;
VectorCopy ( trace . plane . normal , pr_global_struct - > V_trace_plane_normal ) ;
pr_global_struct - > trace_plane_dist = trace . plane . dist ;
if ( trace . ent )
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , trace . ent ) ;
else
pr_global_struct - > trace_ent = EDICT_TO_PROG ( prinst , sv . edicts ) ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_checkpos
Returns true if the given entity can move to the given position from it ' s
current position by walking or rolling .
FIXME : make work . . .
scalar checkpos ( entity , vector )
= = = = = = = = = = = = = = = = =
*/
void PF_checkpos ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
}
//============================================================================
qbyte checkpvsbuffer [ MAX_MAP_LEAFS / 8 ] ;
qbyte * checkpvs ;
int PF_newcheckclient ( progfuncs_t * prinst , int check )
{
int i ;
// qbyte *pvs;
edict_t * ent ;
int leaf ;
vec3_t org ;
// cycle to the next one
if ( check < 1 )
check = 1 ;
if ( check > sv . allocated_client_slots )
check = sv . allocated_client_slots ;
if ( check = = sv . allocated_client_slots )
i = 1 ;
else
i = check + 1 ;
for ( ; ; i + + )
{
if ( i = = sv . allocated_client_slots + 1 )
i = 1 ;
ent = EDICT_NUM ( prinst , i ) ;
if ( i = = check )
break ; // didn't find anything else
if ( ent - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > flags & FL_NOTARGET )
2004-08-23 00:15:46 +00:00
continue ;
// anything that is a client, or has a client as an enemy
break ;
}
// get the PVS for the entity
2005-03-28 00:11:59 +00:00
VectorAdd ( ent - > v - > origin , ent - > v - > view_ofs , org ) ;
2004-08-23 00:15:46 +00:00
leaf = sv . worldmodel - > funcs . LeafForPoint ( org , sv . worldmodel ) ;
checkpvs = sv . worldmodel - > funcs . LeafPVS ( leaf , sv . worldmodel , checkpvsbuffer ) ;
return i ;
}
/*
= = = = = = = = = = = = = = = = =
PF_checkclient
Returns a client ( or object that has a client enemy ) that would be a
valid target .
If there are more than one valid options , they are cycled each frame
If ( self . origin + self . viewofs ) is not in the PVS of the current target ,
it is not returned at all .
name checkclient ( )
= = = = = = = = = = = = = = = = =
*/
# define MAX_CHECK 16
int c_invis , c_notvis ;
void PF_checkclient ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent , * self ;
int l ;
vec3_t view ;
// find a new check if on a new frame
if ( sv . time - sv . lastchecktime > = 0.1 )
{
sv . lastcheck = PF_newcheckclient ( prinst , sv . lastcheck ) ;
sv . lastchecktime = sv . time ;
}
// return check if it might be visible
ent = EDICT_NUM ( prinst , sv . lastcheck ) ;
2005-03-28 00:11:59 +00:00
if ( ent - > isfree | | ent - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
{
RETURN_EDICT ( prinst , sv . edicts ) ;
return ;
}
// if current entity can't possibly see the check entity, return 0
self = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
2005-03-28 00:11:59 +00:00
VectorAdd ( self - > v - > origin , self - > v - > view_ofs , view ) ;
2004-08-23 00:15:46 +00:00
l = sv . worldmodel - > funcs . LeafForPoint ( view , sv . worldmodel ) - 1 ;
if ( ( l < 0 ) | | ! ( checkpvs [ l > > 3 ] & ( 1 < < ( l & 7 ) ) ) )
{
c_notvis + + ;
RETURN_EDICT ( prinst , sv . edicts ) ;
return ;
}
// might be able to see it
c_invis + + ;
RETURN_EDICT ( prinst , ent ) ;
}
//============================================================================
/*
= = = = = = = = = = = = = = = = =
PF_stuffcmd
Sends text over to the client ' s execution buffer
stuffcmd ( clientent , value )
= = = = = = = = = = = = = = = = =
*/
void PF_stuffcmd ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int entnum ;
char * str ;
client_t * cl ;
static qboolean expectingcolour ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
return ;
// PR_BIError ("Parm 0 not a client");
str = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
cl = & svs . clients [ entnum - 1 ] ;
if ( strcmp ( str , " disconnect \n " ) = = 0 )
{
// so long and thanks for all the fish
if ( cl - > netchan . remote_address . type = = NA_LOOPBACK )
return ; //don't drop the local client. It looks wrong.
cl - > drop = true ;
return ;
}
if ( progstype ! = PROG_QW )
{
if ( ! strncmp ( str , " color " , 6 ) ) //okay, so this is a hack, but it fixes the qw scoreboard
{
expectingcolour = true ;
2004-09-30 22:22:32 +00:00
if ( ! strcmp ( str , " color " ) )
return ;
else
str + = 6 ;
2004-08-23 00:15:46 +00:00
}
if ( expectingcolour )
{
int team = atoi ( str ) ;
char * tname ;
expectingcolour = false ;
switch ( team )
{
case 4 : tname = " red " ; break ;
case 13 : tname = " blue " ; break ;
default : tname = va ( " t%i " , team ) ; break ; //good job our va has multiple buffers
}
ClientReliableWrite_Begin ( cl , svc_stufftext , 2 + strlen ( " team XXXXXX \n " ) ) ;
ClientReliableWrite_String ( cl , va ( " team %s \n " , tname ) ) ;
ClientReliableWrite_Begin ( cl , svc_stufftext , 2 + strlen ( " color " ) ) ;
ClientReliableWrite_String ( cl , " color " ) ;
}
}
if ( cl - > controller )
{ //this is a slave client.
//find the right number and send.
int pnum = 0 ;
client_t * sp ;
for ( sp = cl - > controller ; sp ; sp = sp - > controlled )
{
if ( sp = = cl )
break ;
pnum + + ;
}
sp = cl - > controller ;
ClientReliableWrite_Begin ( sp , svc_choosesplitclient , 4 + strlen ( str ) ) ;
ClientReliableWrite_Byte ( sp , pnum ) ;
ClientReliableWrite_Byte ( sp , svc_stufftext ) ;
ClientReliableWrite_String ( sp , str ) ;
}
else
{
ClientReliableWrite_Begin ( cl , svc_stufftext , 2 + strlen ( str ) ) ;
ClientReliableWrite_String ( cl , str ) ;
}
}
2004-11-17 17:52:18 +00:00
//DP_QC_DROPCLIENT
void PF_dropclient ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int entnum ;
client_t * cl ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
return ;
cl = & svs . clients [ entnum - 1 ] ;
// so long and thanks for all the fish
if ( cl - > netchan . remote_address . type = = NA_LOOPBACK )
return ; //don't drop the local client. It looks wrong.
cl - > drop = true ;
return ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_localcmd
Sends text over to the client ' s execution buffer
localcmd ( string )
= = = = = = = = = = = = = = = = =
*/
void PF_localcmd ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * str ;
str = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
if ( ! strcmp ( str , " host_framerate 0 \n " ) )
2005-04-26 16:04:12 +00:00
Cbuf_AddText ( " sv_mintic 0 \n " , RESTRICT_INSECURE ) ; //hmm... do this better...
2004-08-23 00:15:46 +00:00
else
2005-04-26 16:04:12 +00:00
Cbuf_AddText ( str , RESTRICT_INSECURE ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
PF_cvar
float cvar ( string )
= = = = = = = = = = = = = = = = =
*/
2004-11-21 07:31:26 +00:00
static void PF_cvar ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
char * str ;
str = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
if ( ! strcmp ( str , " pr_checkextension " ) ) //no console changing
2004-09-13 02:22:02 +00:00
G_FLOAT ( OFS_RETURN ) = PR_EnableEBFSBuiltin ( " checkextension " , 0 ) ;
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( str , " pr_builtin_find " ) )
2004-09-13 02:22:02 +00:00
G_FLOAT ( OFS_RETURN ) = PR_EnableEBFSBuiltin ( " builtin_find " , 0 ) ;
2004-10-13 06:37:44 +00:00
else if ( ! strcmp ( str , " pr_map_builtin " ) )
G_FLOAT ( OFS_RETURN ) = PR_EnableEBFSBuiltin ( " map_builtin " , 0 ) ;
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( str , " halflifebsp " ) )
G_FLOAT ( OFS_RETURN ) = sv . worldmodel - > fromgame = = fg_halflife ;
else
G_FLOAT ( OFS_RETURN ) = Cvar_VariableValue ( str ) ;
}
void PF_cvar_string ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * str ;
str = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
RETURN_CSTRING ( Cvar_VariableString ( str ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_cvar_set
float cvar ( string )
= = = = = = = = = = = = = = = = =
*/
void PF_cvar_set ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * var_name , * val ;
cvar_t * var ;
var_name = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
val = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
var = Cvar_FindVar ( var_name ) ;
if ( ! var )
Con_Printf ( " PF_cvar_set: variable %s not found \n " , var_name ) ;
else
Cvar_Set ( var , val ) ;
}
2004-08-31 23:58:18 +00:00
void PF_cvar_setf ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * var_name ;
float val ;
cvar_t * var ;
var_name = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
val = G_FLOAT ( OFS_PARM1 ) ;
var = Cvar_FindVar ( var_name ) ;
if ( ! var )
Con_Printf ( " PF_cvar_set: variable %s not found \n " , var_name ) ;
else
Cvar_SetValue ( var , val ) ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_registercvar
float registercvar ( string name , string value )
= = = = = = = = = = = = = = = = =
*/
void PF_registercvar ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * name , * value ;
value = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
if ( Cvar_FindVar ( value ) )
G_FLOAT ( OFS_RETURN ) = 0 ;
else
{
name = BZ_Malloc ( strlen ( value ) + 1 ) ;
strcpy ( name , value ) ;
2004-09-04 17:52:32 +00:00
if ( * prinst - > callargc > 1 )
value = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
else
value = " " ;
2004-08-23 00:15:46 +00:00
// archive?
if ( Cvar_Get ( name , value , CVAR_USERCREATED , " QC created vars " ) )
G_FLOAT ( OFS_RETURN ) = 1 ;
else
G_FLOAT ( OFS_RETURN ) = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = =
PF_findradius
Returns a chain of entities that have origins within a spherical area
findradius ( origin , radius )
= = = = = = = = = = = = = = = = =
*/
void PF_findradius ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent , * chain ;
float rad ;
float * org ;
vec3_t eorg ;
int i , j ;
chain = ( edict_t * ) sv . edicts ;
org = G_VECTOR ( OFS_PARM0 ) ;
rad = G_FLOAT ( OFS_PARM1 ) ;
for ( i = 1 ; i < sv . num_edicts ; i + + )
{
ent = EDICT_NUM ( svprogfuncs , i ) ;
if ( ent - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > solid = = SOLID_NOT )
2004-08-23 00:15:46 +00:00
continue ;
for ( j = 0 ; j < 3 ; j + + )
2005-03-28 00:11:59 +00:00
eorg [ j ] = org [ j ] - ( ent - > v - > origin [ j ] + ( ent - > v - > mins [ j ] + ent - > v - > maxs [ j ] ) * 0.5 ) ;
2004-08-23 00:15:46 +00:00
if ( Length ( eorg ) > rad )
continue ;
2005-03-28 00:11:59 +00:00
ent - > v - > chain = EDICT_TO_PROG ( prinst , chain ) ;
2004-08-23 00:15:46 +00:00
chain = ent ;
}
RETURN_EDICT ( prinst , chain ) ;
}
/*
= = = = = = = = =
PF_dprint
= = = = = = = = =
*/
void PF_dprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2005-03-07 08:55:30 +00:00
{
Con_DPrintf ( " %s " , PF_VarString ( prinst , 0 , pr_globals ) ) ;
}
/*
= = = = = = = = =
PF_print
= = = = = = = = =
*/
void PF_print ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
Con_Printf ( " %s " , PF_VarString ( prinst , 0 , pr_globals ) ) ;
}
/*
= = = = = = = = =
PF_conprint
= = = = = = = = =
*/
void PF_conprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
Sys_Printf ( " %s " , PF_VarString ( prinst , 0 , pr_globals ) ) ;
}
2005-03-07 08:55:30 +00:00
void PF_printf ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
char temp [ 256 ] ;
float v ;
v = G_FLOAT ( OFS_PARM1 ) ;
if ( v = = ( int ) v )
sprintf ( temp , " %d " , ( int ) v ) ;
else
sprintf ( temp , " %5.1f " , v ) ;
Con_Printf ( PR_GetStringOfs ( prinst , OFS_PARM0 ) , temp ) ;
}
2005-03-07 08:55:30 +00:00
void PF_printv ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
char temp [ 256 ] ;
sprintf ( temp , " '%5.1f %5.1f %5.1f' " , G_VECTOR ( OFS_PARM1 ) [ 0 ] , G_VECTOR ( OFS_PARM1 ) [ 1 ] , G_VECTOR ( OFS_PARM1 ) [ 2 ] ) ;
Con_Printf ( PR_GetStringOfs ( prinst , OFS_PARM0 ) , temp ) ;
}
# define MAX_TEMPSTRS 16
2005-02-28 07:16:19 +00:00
# define MAXTEMPBUFFERLEN 4096
2005-05-20 03:32:53 +00:00
char * PF_TempStr ( progfuncs_t * prinst )
{
if ( prinst - > tempstringnum = = MAX_TEMPSTRS )
prinst - > tempstringnum = 0 ;
return prinst - > tempstringbase + ( prinst - > tempstringnum + + ) * MAXTEMPBUFFERLEN ;
}
void PF_InitTempStrings ( progfuncs_t * prinst )
2004-08-23 00:15:46 +00:00
{
2005-05-20 03:32:53 +00:00
prinst - > tempstringbase = prinst - > AddString ( prinst , " " , MAXTEMPBUFFERLEN * MAX_TEMPSTRS ) ;
prinst - > tempstringnum = 0 ;
2004-08-23 00:15:46 +00:00
}
void PF_ftos ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float v ;
2005-05-20 03:32:53 +00:00
char * pr_string_temp = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
v = G_FLOAT ( OFS_PARM0 ) ;
if ( v = = ( int ) v )
sprintf ( pr_string_temp , " %d " , ( int ) v ) ;
else
sprintf ( pr_string_temp , " %5.1f " , v ) ;
RETURN_TSTRING ( pr_string_temp ) ;
}
void PF_ftosp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float v ;
int num ;
2005-05-20 03:32:53 +00:00
char * pr_string_temp = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
v = G_FLOAT ( OFS_PARM0 ) ;
num = G_FLOAT ( OFS_PARM1 ) ;
switch ( num )
{
case 1 :
sprintf ( pr_string_temp , " %1f " , v ) ;
break ;
case 2 :
sprintf ( pr_string_temp , " %2f " , v ) ;
break ;
case 3 :
sprintf ( pr_string_temp , " %3f " , v ) ;
break ;
case 4 :
sprintf ( pr_string_temp , " %4f " , v ) ;
break ;
default :
sprintf ( pr_string_temp , " %f " , v ) ;
break ;
}
RETURN_TSTRING ( pr_string_temp ) ;
}
void PF_fabs ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float v ;
v = G_FLOAT ( OFS_PARM0 ) ;
G_FLOAT ( OFS_RETURN ) = fabs ( v ) ;
}
void PF_vtos ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-20 03:32:53 +00:00
char * pr_string_temp = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
sprintf ( pr_string_temp , " '%5.1f %5.1f %5.1f' " , G_VECTOR ( OFS_PARM0 ) [ 0 ] , G_VECTOR ( OFS_PARM0 ) [ 1 ] , G_VECTOR ( OFS_PARM0 ) [ 2 ] ) ;
RETURN_TSTRING ( pr_string_temp ) ;
}
void PF_Spawn ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-11-21 07:31:26 +00:00
struct edict_s * ed ;
2004-08-23 00:15:46 +00:00
ed = ED_Alloc ( prinst ) ;
RETURN_EDICT ( prinst , ed ) ;
}
void PF_spawn_temp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ed ;
ed = ED_Alloc ( prinst ) ;
RETURN_EDICT ( prinst , ed ) ;
}
void PF_Remove ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ed ;
ed = G_EDICT ( prinst , OFS_PARM0 ) ;
2004-11-21 07:31:26 +00:00
if ( ed - > isfree & & progstype ! = PROG_H2 ) //h2 is dire...
2004-08-23 00:15:46 +00:00
{
Con_DPrintf ( " Tried removing free entity \n " ) ;
return ; //yeah, alright, so this is hacky.
}
ED_Free ( prinst , ed ) ;
}
// entity (entity start, .string field, string match) find = #5;
2004-11-21 07:31:26 +00:00
void PF_FindString ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
int e ;
int f ;
2005-05-15 18:49:04 +00:00
char * s ;
string_t t ;
2004-08-23 00:15:46 +00:00
edict_t * ed ;
e = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
f = G_INT ( OFS_PARM1 ) + prinst - > fieldadjust ;
s = PR_GetStringOfs ( prinst , OFS_PARM2 ) ;
if ( ! s )
{
2004-11-21 07:31:26 +00:00
PR_BIError ( prinst , " PF_FindString: bad search string " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2004-11-21 07:31:26 +00:00
for ( e + + ; e < * prinst - > parms - > sv_num_edicts ; e + + )
2004-08-23 00:15:46 +00:00
{
ed = EDICT_NUM ( prinst , e ) ;
if ( ed - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
t = ( ( string_t * ) ed - > v ) [ f ] ;
2004-08-23 00:15:46 +00:00
if ( ! t )
continue ;
if ( ! strcmp ( t + prinst - > stringtable , s ) )
{
RETURN_EDICT ( prinst , ed ) ;
return ;
}
}
2004-11-21 07:31:26 +00:00
RETURN_EDICT ( prinst , * prinst - > parms - > sv_edicts ) ;
2004-08-23 00:15:46 +00:00
}
/*
void PR_CheckEmptyString ( char * s )
{
if ( s [ 0 ] < = ' ' )
PR_RunError ( " Bad string " ) ;
}
*/
void PF_precache_file ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{ // precache_file is only used to copy files with qcc, it does nothing
G_INT ( OFS_RETURN ) = G_INT ( OFS_PARM0 ) ;
}
void PF_precache_sound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int i ;
2005-05-13 10:42:48 +00:00
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
/*
2004-08-23 00:15:46 +00:00
if ( sv . state ! = ss_loading )
{
2005-05-13 10:42:48 +00:00
PR_BIError ( prinst , " PF_Precache_*: Precache can only be done in spawn functions (%s) " , s ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-05-13 10:42:48 +00:00
*/
2004-08-23 00:15:46 +00:00
G_INT ( OFS_RETURN ) = G_INT ( OFS_PARM0 ) ;
if ( s [ 0 ] < = ' ' )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_precache_sound: Bad string " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
for ( i = 1 ; i < MAX_SOUNDS ; i + + )
{
if ( ! * sv . sound_precache [ i ] )
{
strcpy ( sv . sound_precache [ i ] , s ) ;
2005-05-26 12:55:34 +00:00
if ( sv . state ! = ss_loading )
{
MSG_WriteByte ( & sv . reliable_datagram , svc_precache ) ;
MSG_WriteShort ( & sv . reliable_datagram , i + 32768 ) ;
MSG_WriteString ( & sv . reliable_datagram , s ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqreliable_datagram , svcdp_precache ) ;
MSG_WriteShort ( & sv . nqreliable_datagram , i + 32768 ) ;
MSG_WriteString ( & sv . nqreliable_datagram , s ) ;
# endif
}
2004-08-23 00:15:46 +00:00
return ;
}
if ( ! strcmp ( sv . sound_precache [ i ] , s ) )
return ;
}
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_precache_sound: overflow " ) ;
2004-08-23 00:15:46 +00:00
}
void PF_precache_model ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int i ;
2005-05-13 10:42:48 +00:00
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
/*
2004-08-23 00:15:46 +00:00
if ( sv . state ! = ss_loading )
{
2005-05-13 10:42:48 +00:00
PR_BIError ( prinst , " PF_Precache_*: Precache can only be done in spawn functions (%s) " , s ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = 1 ;
return ;
}
2005-05-13 10:42:48 +00:00
*/
2004-08-23 00:15:46 +00:00
G_INT ( OFS_RETURN ) = G_INT ( OFS_PARM0 ) ;
if ( s [ 0 ] < = ' ' )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Bad string " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
for ( i = 1 ; i < MAX_MODELS ; i + + )
{
2005-05-17 02:36:54 +00:00
if ( ! sv . model_precache [ i ] )
2004-08-23 00:15:46 +00:00
{
2005-05-17 02:36:54 +00:00
if ( strlen ( s ) > = MAX_QPATH - 1 ) //probably safest to keep this.
2004-11-21 07:31:26 +00:00
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Precache name too long " ) ;
2004-11-21 07:31:26 +00:00
return ;
}
2005-05-17 02:36:54 +00:00
sv . model_precache [ i ] = PR_AddString ( prinst , s , 0 ) ;
2004-08-23 00:15:46 +00:00
if ( ! strcmp ( s + strlen ( s ) - 4 , " .bsp " ) )
sv . models [ i ] = Mod_FindName ( sv . model_precache [ i ] ) ;
2005-05-26 12:55:34 +00:00
if ( sv . state ! = ss_loading )
{
MSG_WriteByte ( & sv . reliable_datagram , svc_precache ) ;
MSG_WriteShort ( & sv . reliable_datagram , i ) ;
MSG_WriteString ( & sv . reliable_datagram , s ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqreliable_datagram , svcdp_precache ) ;
MSG_WriteShort ( & sv . nqreliable_datagram , i ) ;
MSG_WriteString ( & sv . nqreliable_datagram , s ) ;
# endif
}
2004-08-23 00:15:46 +00:00
return ;
}
if ( ! strcmp ( sv . model_precache [ i ] , s ) )
{
return ;
}
}
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_precache_model: overflow " ) ;
2004-08-23 00:15:46 +00:00
}
void PF_precache_puzzle_model ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{ //qc/hc lacks string manipulation.
char * shortname ;
char fullname [ MAX_QPATH ] ;
shortname = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
_snprintf ( fullname , sizeof ( fullname ) - 1 , " models/puzzle/%s.mdl " , shortname ) ;
G_INT ( OFS_PARM0 ) = ( int ) ( fullname - prinst - > stringtable ) ;
PF_precache_model ( prinst , pr_globals ) ;
G_INT ( OFS_PARM0 ) = ( int ) ( shortname - prinst - > stringtable ) ; //piece of mind.
}
void PF_WeapIndex ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int i ;
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
G_FLOAT ( OFS_RETURN ) = 1 ;
if ( s [ 0 ] < = ' ' )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Bad string " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
for ( i = 1 ; i < MAX_MODELS ; i + + )
{
if ( ! * sv . model_precache [ i ] )
{
if ( sv . state ! = ss_loading ) //allow it to be used to find a model too.
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_Precache_*: Precache can only be done in spawn functions " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
strcpy ( sv . model_precache [ i ] , s ) ;
if ( ! strcmp ( s + strlen ( s ) - 4 , " .bsp " ) )
sv . models [ i ] = Mod_FindName ( sv . model_precache [ i ] ) ;
G_FLOAT ( OFS_RETURN ) = i ;
return ;
}
if ( ! strcmp ( sv . model_precache [ i ] , s ) )
{
G_FLOAT ( OFS_RETURN ) = i ;
return ;
}
}
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_precache_model: overflow " ) ;
2004-08-23 00:15:46 +00:00
}
void PF_coredump ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-19 02:53:03 +00:00
int size = 1024 * 1024 * 8 ;
char * buffer = BZ_Malloc ( size ) ;
prinst - > save_ents ( prinst , buffer , & size , 3 ) ;
COM_WriteFile ( " ssqccore.txt " , buffer , size ) ;
BZ_Free ( buffer ) ;
2004-08-23 00:15:46 +00:00
}
void PF_traceon ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = true ;
2004-08-23 00:15:46 +00:00
}
void PF_traceoff ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = false ;
2004-08-23 00:15:46 +00:00
}
void PF_eprint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char buffer [ 8192 ] ;
char * buf ;
int size = sizeof ( buffer ) ;
buf = prinst - > saveent ( prinst , buffer , & size , G_EDICT ( prinst , OFS_PARM0 ) ) ;
Con_Printf ( " Entity %i: \n %s \n " , G_EDICTNUM ( prinst , OFS_PARM0 ) , buf ) ;
}
/*
= = = = = = = = = = = = = = =
PF_walkmove
float ( float yaw , float dist ) walkmove
= = = = = = = = = = = = = = =
*/
void PF_walkmove ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
float yaw , dist ;
vec3_t move ;
// dfunction_t *oldf;
int oldself ;
struct globalvars_s * settrace ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
yaw = G_FLOAT ( OFS_PARM0 ) ;
dist = G_FLOAT ( OFS_PARM1 ) ;
if ( * svprogfuncs - > callargc > = 3 & & G_FLOAT ( OFS_PARM2 ) )
settrace = pr_globals ;
else
settrace = NULL ;
2005-03-28 00:11:59 +00:00
if ( ! ( ( int ) ent - > v - > flags & ( FL_ONGROUND | FL_FLY | FL_SWIM ) ) )
2004-08-23 00:15:46 +00:00
{
G_FLOAT ( OFS_RETURN ) = 0 ;
return ;
}
yaw = yaw * M_PI * 2 / 360 ;
move [ 0 ] = cos ( yaw ) * dist ;
move [ 1 ] = sin ( yaw ) * dist ;
move [ 2 ] = 0 ;
// save program state, because SV_movestep may call other progs
// oldf = pr_xfunction;
oldself = pr_global_struct - > self ;
2005-01-04 07:58:19 +00:00
2005-05-26 12:55:34 +00:00
// if (!dist)
// {
// G_FLOAT(OFS_RETURN) = !SV_TestEntityPosition(ent);
// }
// else if (!SV_TestEntityPosition(ent))
// {
2004-12-08 04:14:52 +00:00
G_FLOAT ( OFS_RETURN ) = SV_movestep ( ent , move , true , false , settrace ) ;
2005-05-26 12:55:34 +00:00
// if (SV_TestEntityPosition(ent))
// Con_Printf("Entity became stuck\n");
// }
2004-08-23 00:15:46 +00:00
// restore program state
// pr_xfunction = oldf;
pr_global_struct - > self = oldself ;
}
/*
= = = = = = = = = = = = = = =
PF_droptofloor
void ( ) droptofloor
= = = = = = = = = = = = = = =
*/
void PF_droptofloor ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
vec3_t end ;
vec3_t start ;
trace_t trace ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
2005-03-28 00:11:59 +00:00
VectorCopy ( ent - > v - > origin , end ) ;
2004-08-23 00:15:46 +00:00
end [ 2 ] - = 512 ;
2005-03-28 00:11:59 +00:00
VectorCopy ( ent - > v - > origin , start ) ;
trace = SV_Move ( start , ent - > v - > mins , ent - > v - > maxs , end , MOVE_NORMAL , ent ) ;
2004-08-23 00:15:46 +00:00
if ( trace . fraction = = 1 | | trace . allsolid )
G_FLOAT ( OFS_RETURN ) = 0 ;
else
{
2005-03-28 00:11:59 +00:00
VectorCopy ( trace . endpos , ent - > v - > origin ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( ent , false ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > flags = ( int ) ent - > v - > flags | FL_ONGROUND ;
ent - > v - > groundentity = EDICT_TO_PROG ( prinst , trace . ent ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = 1 ;
}
}
/*
= = = = = = = = = = = = = = =
PF_lightstyle
2004-12-19 04:37:42 +00:00
void ( float style , string value [ , float colour ] ) lightstyle
2004-08-23 00:15:46 +00:00
= = = = = = = = = = = = = = =
*/
void PF_lightstyle ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int style ;
char * val ;
client_t * client ;
int j ;
# ifdef PEXT_LIGHTSTYLECOL
int col ;
if ( * svprogfuncs - > callargc > = 3 )
{
col = G_FLOAT ( OFS_PARM2 ) ;
if ( IS_NAN ( col ) | | ! col | | col > 0x111 )
col = 7 ;
}
else col = 7 ;
# endif
style = G_FLOAT ( OFS_PARM0 ) ;
val = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
if ( style < 0 | | style > = MAX_LIGHTSTYLES )
{
Con_Printf ( " WARNING: Bad lightstyle %i. \n " , style ) ;
return ;
}
if ( strlen ( val ) > MAX_STYLESTRING - 1 )
Con_Printf ( " WARNING: Style string is longer than standard (%i). Some clients could crash. \n " , MAX_STYLESTRING - 1 ) ;
// change the string in sv
if ( sv . lightstyles [ style ] )
Z_Free ( sv . lightstyles [ style ] ) ;
sv . lightstyles [ style ] = Z_Malloc ( strlen ( val ) + 1 ) ;
strcpy ( sv . lightstyles [ style ] , val ) ;
// sv.lightstyles[style] = val;
# ifdef PEXT_LIGHTSTYLECOL
sv . lightstylecolours [ style ] = col ;
# endif
// send message to all clients on this server
if ( sv . state ! = ss_active )
return ;
for ( j = 0 , client = svs . clients ; j < sv . allocated_client_slots ; j + + , client + + )
{
if ( client - > controller )
continue ;
if ( client - > state = = cs_spawned )
{
# ifdef PEXT_LIGHTSTYLECOL
if ( client - > fteprotocolextensions & PEXT_LIGHTSTYLECOL & & col ! = 7 )
{
ClientReliableWrite_Begin ( client , svc_lightstylecol , strlen ( val ) + 4 ) ;
ClientReliableWrite_Char ( client , style ) ;
ClientReliableWrite_Char ( client , col ) ;
ClientReliableWrite_String ( client , val ) ;
}
else
{
# endif
ClientReliableWrite_Begin ( client , svc_lightstyle , strlen ( val ) + 3 ) ;
ClientReliableWrite_Char ( client , style ) ;
ClientReliableWrite_String ( client , val ) ;
# ifdef PEXT_LIGHTSTYLECOL
}
# endif
}
}
}
void PF_lightstylevalue ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int style ;
style = G_FLOAT ( OFS_PARM0 ) ;
if ( style < 0 | | style > = MAX_LIGHTSTYLES | | ! sv . lightstyles [ style ] )
{
G_FLOAT ( OFS_RETURN ) = 0 ;
return ;
}
G_FLOAT ( OFS_RETURN ) = * sv . lightstyles [ style ] - ' a ' ;
}
void PF_lightstylestatic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int style ;
float num ;
char * val ;
client_t * client ;
int j ;
static char * styleDefs [ ] =
{
" a " , " b " , " c " , " d " , " e " , " f " , " g " ,
" h " , " i " , " j " , " k " , " l " , " m " , " n " ,
" o " , " p " , " q " , " r " , " s " , " t " , " u " ,
" v " , " w " , " x " , " y " , " z "
} ;
# ifdef PEXT_LIGHTSTYLECOL
int col ;
if ( * svprogfuncs - > callargc > = 3 )
{
col = G_FLOAT ( OFS_PARM2 ) ;
if ( IS_NAN ( col ) | | ! col | | col > 0x111 )
col = 7 ;
}
else col = 7 ;
# endif
style = G_FLOAT ( OFS_PARM0 ) ;
num = G_FLOAT ( OFS_PARM1 ) ;
if ( num < 0 )
num = 0 ;
else if ( num > = ' z ' - ' a ' )
num = ' z ' - ' a ' - 1 ;
val = styleDefs [ ( int ) num ] ;
if ( style < 0 | | style > = MAX_LIGHTSTYLES )
{
Con_Printf ( " WARNING: Bad lightstyle %i. \n " , style ) ;
return ;
}
if ( strlen ( val ) > MAX_STYLESTRING - 1 )
Con_Printf ( " WARNING: Style string is longer than standard (%i). Some clients could crash. \n " , MAX_STYLESTRING - 1 ) ;
// change the string in sv
if ( sv . lightstyles [ style ] )
Z_Free ( sv . lightstyles [ style ] ) ;
sv . lightstyles [ style ] = Z_Malloc ( strlen ( val ) + 1 ) ;
strcpy ( sv . lightstyles [ style ] , val ) ;
// sv.lightstyles[style] = val;
# ifdef PEXT_LIGHTSTYLECOL
sv . lightstylecolours [ style ] = col ;
# endif
// send message to all clients on this server
if ( sv . state ! = ss_active )
return ;
for ( j = 0 , client = svs . clients ; j < sv . allocated_client_slots ; j + + , client + + )
{
if ( client - > controller )
continue ;
if ( client - > state = = cs_spawned )
{
# ifdef PEXT_LIGHTSTYLECOL
if ( client - > fteprotocolextensions & PEXT_LIGHTSTYLECOL & & col ! = 7 )
{
ClientReliableWrite_Begin ( client , svc_lightstylecol , strlen ( val ) + 4 ) ;
ClientReliableWrite_Char ( client , style ) ;
ClientReliableWrite_Char ( client , col ) ;
ClientReliableWrite_String ( client , val ) ;
}
else
{
# endif
ClientReliableWrite_Begin ( client , svc_lightstyle , strlen ( val ) + 3 ) ;
ClientReliableWrite_Char ( client , style ) ;
ClientReliableWrite_String ( client , val ) ;
# ifdef PEXT_LIGHTSTYLECOL
}
# endif
}
}
}
void PF_rint ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float f ;
f = G_FLOAT ( OFS_PARM0 ) ;
if ( f > 0 )
G_FLOAT ( OFS_RETURN ) = ( int ) ( f + 0.5 ) ;
else
G_FLOAT ( OFS_RETURN ) = ( int ) ( f - 0.5 ) ;
}
void PF_floor ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = floor ( G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_ceil ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = ceil ( G_FLOAT ( OFS_PARM0 ) ) ;
}
/*
= = = = = = = = = = = = =
PF_checkbottom
= = = = = = = = = = = = =
*/
void PF_checkbottom ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
ent = G_EDICT ( prinst , OFS_PARM0 ) ;
G_FLOAT ( OFS_RETURN ) = SV_CheckBottom ( ent ) ;
}
/*
= = = = = = = = = = = = =
PF_pointcontents
= = = = = = = = = = = = =
*/
void PF_pointcontents ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * v ;
int cont ;
v = G_VECTOR ( OFS_PARM0 ) ;
cont = SV_PointContents ( v ) ;
if ( cont & FTECONTENTS_SOLID )
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_SOLID ;
else if ( cont & FTECONTENTS_SKY )
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_SKY ;
else if ( cont & FTECONTENTS_LAVA )
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_LAVA ;
else if ( cont & FTECONTENTS_SLIME )
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_SLIME ;
else if ( cont & FTECONTENTS_WATER )
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_WATER ;
else
G_FLOAT ( OFS_RETURN ) = Q1CONTENTS_EMPTY ;
}
/*
= = = = = = = = = = = = =
PF_nextent
entity nextent ( entity )
= = = = = = = = = = = = =
*/
void PF_nextent ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
edict_t * ent ;
i = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
while ( 1 )
{
i + + ;
2004-11-21 07:31:26 +00:00
if ( i = = * prinst - > parms - > sv_num_edicts )
2004-08-23 00:15:46 +00:00
{
2004-11-21 07:31:26 +00:00
RETURN_EDICT ( prinst , * prinst - > parms - > sv_edicts ) ;
2004-08-23 00:15:46 +00:00
return ;
}
/* if (i <= MAX_CLIENTS)
{
if ( ! svs . clients [ i - 1 ] . state )
continue ;
} */
ent = EDICT_NUM ( prinst , i ) ;
if ( ! ent - > isfree )
{
RETURN_EDICT ( prinst , ent ) ;
return ;
}
}
}
/*
= = = = = = = = = = = = =
PF_aim
Pick a vector for the player to shoot along
vector aim ( entity , missilespeed )
= = = = = = = = = = = = =
*/
//cvar_t sv_aim = {"sv_aim", "0.93"};
cvar_t sv_aim = { " sv_aim " , " 2 " } ;
void PF_aim ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent , * check , * bestent ;
vec3_t start , dir , end , bestdir ;
int i , j ;
trace_t tr ;
float dist , bestdist ;
float speed ;
char * noaim ;
ent = G_EDICT ( prinst , OFS_PARM0 ) ;
speed = G_FLOAT ( OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
VectorCopy ( ent - > v - > origin , start ) ;
2004-08-23 00:15:46 +00:00
start [ 2 ] + = 20 ;
// noaim option
i = NUM_FOR_EDICT ( prinst , ent ) ;
if ( i > 0 & & i < sv . allocated_client_slots )
{
noaim = Info_ValueForKey ( svs . clients [ i - 1 ] . userinfo , " noaim " ) ;
if ( atoi ( noaim ) > 0 )
{
VectorCopy ( P_VEC ( v_forward ) , G_VECTOR ( OFS_RETURN ) ) ;
return ;
}
}
// try sending a trace straight
VectorCopy ( P_VEC ( v_forward ) , dir ) ;
VectorMA ( start , 2048 , dir , end ) ;
tr = SV_Move ( start , vec3_origin , vec3_origin , end , false , ent ) ;
2005-03-28 00:11:59 +00:00
if ( tr . ent & & tr . ent - > v - > takedamage = = DAMAGE_AIM
& & ( ! teamplay . value | | ent - > v - > team < = 0 | | ent - > v - > team ! = tr . ent - > v - > team ) )
2004-08-23 00:15:46 +00:00
{
VectorCopy ( P_VEC ( v_forward ) , G_VECTOR ( OFS_RETURN ) ) ;
return ;
}
// try all possible entities
VectorCopy ( dir , bestdir ) ;
bestdist = sv_aim . value ;
bestent = NULL ;
for ( i = 1 ; i < sv . num_edicts ; i + + )
{
check = EDICT_NUM ( prinst , i ) ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > takedamage ! = DAMAGE_AIM )
2004-08-23 00:15:46 +00:00
continue ;
if ( check = = ent )
continue ;
2005-03-28 00:11:59 +00:00
if ( teamplay . value & & ent - > v - > team > 0 & & ent - > v - > team = = check - > v - > team )
2004-08-23 00:15:46 +00:00
continue ; // don't aim at teammate
for ( j = 0 ; j < 3 ; j + + )
2005-03-28 00:11:59 +00:00
end [ j ] = check - > v - > origin [ j ]
+ 0.5 * ( check - > v - > mins [ j ] + check - > v - > maxs [ j ] ) ;
2004-08-23 00:15:46 +00:00
VectorSubtract ( end , start , dir ) ;
VectorNormalize ( dir ) ;
dist = DotProduct ( dir , P_VEC ( v_forward ) ) ;
if ( dist < bestdist )
continue ; // to far to turn
tr = SV_Move ( start , vec3_origin , vec3_origin , end , false , ent ) ;
if ( tr . ent = = check )
{ // can shoot at this one
bestdist = dist ;
bestent = check ;
}
}
if ( bestent )
{
2005-03-28 00:11:59 +00:00
VectorSubtract ( bestent - > v - > origin , ent - > v - > origin , dir ) ;
2004-08-23 00:15:46 +00:00
dist = DotProduct ( dir , P_VEC ( v_forward ) ) ;
VectorScale ( P_VEC ( v_forward ) , dist , end ) ;
end [ 2 ] = dir [ 2 ] ;
VectorNormalize ( end ) ;
VectorCopy ( end , G_VECTOR ( OFS_RETURN ) ) ;
}
else
{
VectorCopy ( bestdir , G_VECTOR ( OFS_RETURN ) ) ;
}
}
/*
= = = = = = = = = = = = = =
PF_changeyaw
This was a major timewaster in progs , so it was converted to C
= = = = = = = = = = = = = =
*/
void PF_changeyaw ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
float ideal , current , move , speed ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
2005-03-28 00:11:59 +00:00
current = anglemod ( ent - > v - > angles [ 1 ] ) ;
ideal = ent - > v - > ideal_yaw ;
speed = ent - > v - > yaw_speed ;
2004-08-23 00:15:46 +00:00
if ( current = = ideal )
return ;
move = ideal - current ;
if ( ideal > current )
{
if ( move > = 180 )
move = move - 360 ;
}
else
{
if ( move < = - 180 )
move = move + 360 ;
}
if ( move > 0 )
{
if ( move > speed )
move = speed ;
}
else
{
if ( move < - speed )
move = - speed ;
}
2005-03-28 00:11:59 +00:00
ent - > v - > angles [ 1 ] = anglemod ( current + move ) ;
2004-08-23 00:15:46 +00:00
}
2004-12-19 04:37:42 +00:00
//void() changepitch = #63;
2004-10-13 06:37:44 +00:00
void PF_changepitch ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
float ideal , current , move , speed ;
eval_t * eval ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
2005-03-28 00:11:59 +00:00
current = anglemod ( ent - > v - > angles [ 1 ] ) ;
2004-10-13 06:37:44 +00:00
eval = prinst - > GetEdictFieldValue ( prinst , ent , " idealpitch " , & evalc_idealpitch ) ;
if ( eval )
ideal = eval - > _float ;
else
ideal = 0 ;
eval = prinst - > GetEdictFieldValue ( prinst , ent , " pitch_speed " , & evalc_pitch_speed ) ;
if ( eval )
speed = eval - > _float ;
else
speed = 0 ;
if ( current = = ideal )
return ;
move = ideal - current ;
if ( ideal > current )
{
if ( move > = 180 )
move = move - 360 ;
}
else
{
if ( move < = - 180 )
move = move + 360 ;
}
if ( move > 0 )
{
if ( move > speed )
move = speed ;
}
else
{
if ( move < - speed )
move = - speed ;
}
2005-03-28 00:11:59 +00:00
ent - > v - > angles [ 1 ] = anglemod ( current + move ) ;
2004-10-13 06:37:44 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MESSAGE WRITING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define MSG_BROADCAST 0 // unreliable to all
# define MSG_ONE 1 // reliable to one (msg_entity)
# define MSG_ALL 2 // reliable to all
# define MSG_INIT 3 // write to the init string
# define MSG_MULTICAST 4 // for multicast()
sizebuf_t * WriteDest ( int dest )
{
switch ( dest )
{
2005-05-08 17:03:19 +00:00
case MSG_PRERELONE :
{
int entnum ;
entnum = PR_globals ( svprogfuncs , PR_CURRENT ) - > param [ 0 ] . i ;
return & svs . clients [ entnum - 1 ] . netchan . message ;
}
2004-08-23 00:15:46 +00:00
case MSG_BROADCAST :
return & sv . datagram ;
case MSG_ONE :
SV_Error ( " Shouldn't be at MSG_ONE " ) ;
#if 0
ent = PROG_TO_EDICT ( pr_global_struct - > msg_entity ) ;
entnum = NUM_FOR_EDICT ( ent ) ;
if ( entnum < 1 | | entnum > MAX_CLIENTS )
{
PR_BIError ( " WriteDest: not a client " ) ;
return & sv . reliable_datagram ;
}
return & svs . clients [ entnum - 1 ] . netchan . message ;
# endif
case MSG_ALL :
return & sv . reliable_datagram ;
case MSG_INIT :
if ( sv . state ! = ss_loading )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( svprogfuncs , " PF_Write_*: MSG_INIT can only be written in spawn functions " ) ;
2004-08-23 00:15:46 +00:00
return NULL ;
}
return & sv . signon ;
case MSG_MULTICAST :
return & sv . multicast ;
default :
2004-11-17 17:52:18 +00:00
PR_BIError ( svprogfuncs , " WriteDest: bad destination " ) ;
2004-08-23 00:15:46 +00:00
break ;
}
return NULL ;
}
# ifdef NQPROT
sizebuf_t * NQWriteDest ( int dest )
{
switch ( dest )
{
2005-05-08 17:03:19 +00:00
case MSG_PRERELONE :
{
int entnum ;
entnum = PR_globals ( svprogfuncs , PR_CURRENT ) - > param [ 0 ] . i ;
return & svs . clients [ entnum - 1 ] . netchan . message ;
}
2004-08-23 00:15:46 +00:00
case MSG_BROADCAST :
return & sv . nqdatagram ;
case MSG_ONE :
SV_Error ( " Shouldn't be at MSG_ONE " ) ;
#if 0
ent = PROG_TO_EDICT ( pr_global_struct - > msg_entity ) ;
entnum = NUM_FOR_EDICT ( ent ) ;
if ( entnum < 1 | | entnum > MAX_CLIENTS )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " WriteDest: not a client " ) ;
2004-08-23 00:15:46 +00:00
return & sv . nqreliable_datagram ;
}
return & svs . clients [ entnum - 1 ] . netchan . message ;
# endif
case MSG_ALL :
return & sv . nqreliable_datagram ;
case MSG_INIT :
if ( sv . state ! = ss_loading )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( svprogfuncs , " PF_Write_*: MSG_INIT can only be written in spawn functions " ) ;
2004-08-23 00:15:46 +00:00
return NULL ;
}
return & sv . signon ;
case MSG_MULTICAST :
return & sv . nqmulticast ;
default :
2004-11-17 17:52:18 +00:00
PR_BIError ( svprogfuncs , " WriteDest: bad destination " ) ;
2004-08-23 00:15:46 +00:00
break ;
}
return NULL ;
}
# endif
struct globalvars_s * pr_netglob ;
progfuncs_t * pr_netprogfuncs ;
client_t * Write_GetClient ( void )
{
int entnum ;
edict_t * ent ;
ent = PROG_TO_EDICT ( pr_netprogfuncs , pr_global_struct - > msg_entity ) ;
entnum = NUM_FOR_EDICT ( pr_netprogfuncs , ent ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
return NULL ; //PR_RunError ("WriteDest: not a client");
return & svs . clients [ entnum - 1 ] ;
}
2005-02-28 07:16:19 +00:00
extern sizebuf_t csqcmsgbuffer ;
2004-08-23 00:15:46 +00:00
void PF_WriteByte ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteByte ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteByte ( G_FLOAT ( OFS_PARM0 ) , ( qbyte ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteByte ( G_FLOAT ( OFS_PARM0 ) , ( qbyte ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
else if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 1 ) ;
ClientReliableWrite_Byte ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteByte ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteChar ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteChar ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteChar ( G_FLOAT ( OFS_PARM0 ) , ( char ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteChar ( G_FLOAT ( OFS_PARM0 ) , ( char ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 1 ) ;
ClientReliableWrite_Char ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteChar ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteShort ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteShort ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteShort ( G_FLOAT ( OFS_PARM0 ) , ( short ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteShort ( G_FLOAT ( OFS_PARM0 ) , ( short ) G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 2 ) ;
ClientReliableWrite_Short ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteShort ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteLong ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteLong ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteLong ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteLong ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 4 ) ;
ClientReliableWrite_Long ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteLong ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteAngle ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteAngle ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteAngle ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteAngle ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 1 ) ;
ClientReliableWrite_Angle ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteAngle ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteCoord ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteCoord ( & csqcmsgbuffer , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteCoord ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteCoord ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 2 ) ;
ClientReliableWrite_Coord ( cl , G_FLOAT ( OFS_PARM1 ) ) ;
}
else
MSG_WriteCoord ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_FLOAT ( OFS_PARM1 ) ) ;
# endif
}
void PF_WriteString ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
char * str = PF_VarString ( prinst , 1 , pr_globals ) ; ;
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteString ( & csqcmsgbuffer , str ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteString ( G_FLOAT ( OFS_PARM0 ) , str ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteString ( G_FLOAT ( OFS_PARM0 ) , str ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 1 + strlen ( str ) ) ;
ClientReliableWrite_String ( cl , str ) ;
}
else
MSG_WriteString ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , str ) ;
# endif
}
void PF_WriteEntity ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_CSQC )
{ //csqc buffers are always written.
MSG_WriteShort ( & csqcmsgbuffer , G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( qc_nonetaccess . value | | sv . demofile )
return ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( progstype = = PROG_NQ | | progstype = = PROG_H2 )
{
NPP_NQWriteEntity ( G_FLOAT ( OFS_PARM0 ) , ( short ) G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
return ;
}
# ifdef NQPROT
else
{
NPP_QWWriteEntity ( G_FLOAT ( OFS_PARM0 ) , ( short ) G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
return ;
}
# else
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
ClientReliableCheckBlock ( cl , 2 ) ;
ClientReliableWrite_Short ( cl , G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
}
else
MSG_WriteShort ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
# endif
}
//small wrapper function.
//void(float target, string str, ...) WriteString2 = #33;
void PF_WriteString2 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int old ;
2005-05-26 12:55:34 +00:00
char * str ;
2005-02-28 07:16:19 +00:00
if ( G_FLOAT ( OFS_PARM0 ) ! = MSG_CSQC & & ( qc_nonetaccess . value | | sv . demofile ) )
2004-08-23 00:15:46 +00:00
return ;
str = PF_VarString ( prinst , 1 , pr_globals ) ;
old = G_FLOAT ( OFS_PARM1 ) ;
while ( * str )
{
G_FLOAT ( OFS_PARM1 ) = * str + + ;
PF_WriteChar ( prinst , pr_globals ) ;
}
G_FLOAT ( OFS_PARM1 ) = old ;
}
2005-05-08 17:03:19 +00:00
void PF_Single_WriteByte ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteByte ( MSG_PRERELONE , ( qbyte ) G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteChar ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteChar ( MSG_PRERELONE , ( char ) G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteShort ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteShort ( MSG_PRERELONE , ( short ) G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteLong ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteLong ( MSG_PRERELONE , G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteAngle ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteAngle ( MSG_PRERELONE , G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteCoord ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteCoord ( MSG_PRERELONE , G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_Single_WriteString ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteString ( MSG_PRERELONE , PF_VarString ( prinst , 1 , pr_globals ) ) ;
}
void PF_Single_WriteEntity ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteEntity ( MSG_PRERELONE , ( short ) G_EDICTNUM ( prinst , OFS_PARM1 ) ) ;
}
void PF_Broadcast_WriteByte ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteByte ( MSG_BROADCAST , ( qbyte ) G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteChar ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteChar ( MSG_BROADCAST , ( char ) G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteShort ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteShort ( MSG_BROADCAST , ( short ) G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteLong ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteLong ( MSG_BROADCAST , G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteAngle ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteAngle ( MSG_BROADCAST , G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteCoord ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteCoord ( MSG_BROADCAST , G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Broadcast_WriteString ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteString ( MSG_BROADCAST , PF_VarString ( prinst , 0 , pr_globals ) ) ;
}
void PF_Broadcast_WriteEntity ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
NPP_NQWriteEntity ( MSG_BROADCAST , ( short ) G_EDICTNUM ( prinst , OFS_PARM0 ) ) ;
}
2004-08-23 00:15:46 +00:00
//======================================================
2004-08-31 23:58:18 +00:00
//copes with any qw point entities.
void SV_point_tempentity ( vec3_t o , int type , int count ) //count (usually 1) is available for some tent types.
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
int split = 0 ;
2004-08-23 00:15:46 +00:00
if ( sv . demofile )
return ;
if ( type > TE_SUPERBULLET ) //pick a new effect, cos this one we don't know about.
type = TE_SPIKE ;
//this is for lamers with old (or unsupported) clients
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-23 00:15:46 +00:00
switch ( type )
{
case TE_BULLET :
MSG_WriteByte ( & sv . multicast , TE_SPIKE ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqmulticast , TE_SPIKE ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-23 00:15:46 +00:00
type = TE_BULLET ;
split = PEXT_TE_BULLET ;
break ;
case TE_SUPERBULLET :
MSG_WriteByte ( & sv . multicast , TE_SUPERSPIKE ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqmulticast , TE_SUPERSPIKE ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-23 00:15:46 +00:00
type = TE_SUPERBULLET ;
split = PEXT_TE_BULLET ;
break ;
2004-08-31 23:58:18 +00:00
case TE_BLOOD :
case TE_GUNSHOT :
MSG_WriteByte ( & sv . multicast , type ) ;
MSG_WriteByte ( & sv . multicast , count ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqmulticast , type ) ; //nq doesn't have a count.
2004-09-07 18:28:25 +00:00
# endif
2004-08-31 23:58:18 +00:00
break ;
case TE_LIGHTNING1 :
case TE_LIGHTNING2 :
case TE_LIGHTNING3 :
SV_Error ( " SV_point_tempentity - type is a beam \n " ) ;
2004-08-23 00:15:46 +00:00
default :
MSG_WriteByte ( & sv . multicast , type ) ;
2005-05-19 02:53:03 +00:00
MSG_WriteByte ( & sv . nqmulticast , type ) ;
2004-08-23 00:15:46 +00:00
}
MSG_WriteCoord ( & sv . multicast , o [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , o [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , o [ 2 ] ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteCoord ( & sv . nqmulticast , o [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , o [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , o [ 2 ] ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-31 23:58:18 +00:00
if ( type = = TE_BLOOD | | type = = TE_LIGHTNINGBLOOD )
{
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
sv . nqmulticast . cursize = 0 ; //don't send a te_blood or lightningblood to an nq client - they'll die horribly.
//send a particle instead
MSG_WriteByte ( & sv . nqmulticast , svc_particle ) ;
MSG_WriteCoord ( & sv . nqmulticast , o [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , o [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , o [ 2 ] ) ;
//no direction.
MSG_WriteChar ( & sv . nqmulticast , 0 ) ;
MSG_WriteChar ( & sv . nqmulticast , 0 ) ;
MSG_WriteChar ( & sv . nqmulticast , 0 ) ;
MSG_WriteByte ( & sv . nqmulticast , count * 20 ) ;
if ( type = = TE_BLOOD )
MSG_WriteByte ( & sv . nqmulticast , 73 ) ;
else
MSG_WriteByte ( & sv . nqmulticast , 225 ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-31 23:58:18 +00:00
}
SV_MulticastProtExt ( o , MULTICAST_PHS , pr_global_struct - > dimension_send , split , 0 ) ;
2004-08-23 00:15:46 +00:00
if ( ! split ) //don't bother sending again.
return ;
2004-08-31 23:58:18 +00:00
//this is for cool people (not nq users)
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , type ) ;
MSG_WriteCoord ( & sv . multicast , o [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , o [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , o [ 2 ] ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( o , MULTICAST_PHS , pr_global_struct - > dimension_send , 0 , split ) ;
}
void SV_beam_tempentity ( int ownerent , vec3_t start , vec3_t end , int type )
{
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , type ) ;
MSG_WriteShort ( & sv . multicast , ownerent ) ;
MSG_WriteCoord ( & sv . multicast , start [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , start [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , start [ 2 ] ) ;
MSG_WriteCoord ( & sv . multicast , end [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , end [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , end [ 2 ] ) ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
if ( type = = TE_LIGHTNING2 & & ownerent < 0 ) //special handling for TE_BEAM (don't do TE_RAILGUN - it's a tomaz extension)
{
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , NQTE_BEAM ) ;
MSG_WriteShort ( & sv . nqmulticast , - 1 - ownerent ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 2 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 2 ] ) ;
}
else
{
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , type ) ;
MSG_WriteShort ( & sv . nqmulticast , ownerent ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , start [ 2 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , end [ 2 ] ) ;
}
2004-09-07 18:28:25 +00:00
# endif
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( start , MULTICAST_PHS , pr_global_struct - > dimension_send , 0 , 0 ) ;
}
void PF_tempentity ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) , 1 ) ;
2004-08-23 00:15:46 +00:00
}
//=============================================================================
int SV_ModelIndex ( char * name ) ;
void PF_makestatic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
int mdlindex , i ;
entity_state_t * state ;
ent = G_EDICT ( prinst , OFS_PARM0 ) ;
SV_FlushSignon ( ) ;
2005-03-28 00:11:59 +00:00
mdlindex = SV_ModelIndex ( PR_GetString ( prinst , ent - > v - > model ) ) ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ent - > v - > drawflags | | ent - > v - > alpha | | mdlindex > 255 | | ent - > v - > frame > 255 | | ent - > v - > scale | | ent - > v - > abslight )
2004-08-23 00:15:46 +00:00
{
if ( sv . numextrastatics = = sizeof ( sv . extendedstatics ) / sizeof ( sv . extendedstatics [ 0 ] ) )
return ; //fail the whole makestatic thing.
state = & sv . extendedstatics [ sv . numextrastatics + + ] ;
memset ( state , 0 , sizeof ( * state ) ) ;
state - > number = sv . numextrastatics ;
state - > flags = 0 ;
2005-03-28 00:11:59 +00:00
VectorCopy ( ent - > v - > origin , state - > origin ) ;
VectorCopy ( ent - > v - > angles , state - > angles ) ;
state - > modelindex = mdlindex ; //ent->v->modelindex;
state - > frame = ent - > v - > frame ;
state - > colormap = ent - > v - > colormap ;
state - > skinnum = ent - > v - > skin ;
state - > effects = ent - > v - > effects ;
2005-05-15 18:49:04 +00:00
state - > hexen2flags = ent - > v - > drawflags ;
2005-03-28 00:11:59 +00:00
state - > abslight = ( int ) ( ent - > v - > abslight * 255 ) & 255 ;
state - > trans = ent - > v - > alpha ;
2004-08-23 00:15:46 +00:00
if ( ! state - > trans )
state - > trans = 1 ;
2005-03-28 00:11:59 +00:00
state - > fatness = ent - > v - > fatness ;
state - > scale = ent - > v - > scale ;
2004-08-23 00:15:46 +00:00
if ( progstype ! = PROG_QW ) //don't send extra nq effects to a qw client.
state - > effects & = EF_BRIGHTLIGHT | EF_DIMLIGHT ;
}
else
{
MSG_WriteByte ( & sv . signon , svc_spawnstatic ) ;
MSG_WriteByte ( & sv . signon , mdlindex & 255 ) ;
2005-03-28 00:11:59 +00:00
MSG_WriteByte ( & sv . signon , ent - > v - > frame ) ;
MSG_WriteByte ( & sv . signon , ( int ) ent - > v - > colormap ) ;
MSG_WriteByte ( & sv . signon , ( int ) ent - > v - > skin ) ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
2005-03-28 00:11:59 +00:00
MSG_WriteCoord ( & sv . signon , ent - > v - > origin [ i ] ) ;
MSG_WriteAngle ( & sv . signon , ent - > v - > angles [ i ] ) ;
2004-08-23 00:15:46 +00:00
}
}
// throw the entity away now
ED_Free ( svprogfuncs , ent ) ;
}
//=============================================================================
/*
= = = = = = = = = = = = = =
PF_setspawnparms
= = = = = = = = = = = = = =
*/
void PF_setspawnparms ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
int i ;
client_t * client ;
ent = G_EDICT ( prinst , OFS_PARM0 ) ;
i = NUM_FOR_EDICT ( prinst , ent ) ;
if ( i < 1 | | i > sv . allocated_client_slots )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " Entity is not a client " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// copy spawn parms out of the client_t
client = svs . clients + ( i - 1 ) ;
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
( & pr_global_struct - > parm1 ) [ i ] = client - > spawn_parms [ i ] ;
}
/*
= = = = = = = = = = = = = =
PF_changelevel
= = = = = = = = = = = = = =
*/
void PF_changelevel ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s , * spot ;
static int last_spawncount ;
// make sure we don't issue two changelevels
if ( svs . spawncount = = last_spawncount )
return ;
last_spawncount = svs . spawncount ;
if ( * svprogfuncs - > callargc = = 2 )
{
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
spot = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
Cbuf_AddText ( va ( " changelevel %s %s \n " , s , spot ) , RESTRICT_LOCAL ) ;
}
else
{
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
Cbuf_AddText ( va ( " map %s \n " , s ) , RESTRICT_LOCAL ) ;
}
}
/*
= = = = = = = = = = = = = =
PF_logfrag
logfrag ( killer , killee )
= = = = = = = = = = = = = =
*/
void PF_logfrag ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent1 , * ent2 ;
int e1 , e2 ;
char * s ;
ent1 = G_EDICT ( prinst , OFS_PARM0 ) ;
ent2 = G_EDICT ( prinst , OFS_PARM1 ) ;
e1 = NUM_FOR_EDICT ( prinst , ent1 ) ;
e2 = NUM_FOR_EDICT ( prinst , ent2 ) ;
if ( e1 < 1 | | e1 > sv . allocated_client_slots
| | e2 < 1 | | e2 > sv . allocated_client_slots )
return ;
# ifdef SVRANKING
if ( e1 ! = e2 ) //don't get a point for suiside.
svs . clients [ e1 - 1 ] . kills + = 1 ;
svs . clients [ e2 - 1 ] . deaths + = 1 ;
# endif
s = va ( " \\ %s \\ %s \\ \n " , svs . clients [ e1 - 1 ] . name , svs . clients [ e2 - 1 ] . name ) ;
SZ_Print ( & svs . log [ svs . logsequence & 1 ] , s ) ;
if ( sv_fraglogfile ) {
fprintf ( sv_fraglogfile , s ) ;
fflush ( sv_fraglogfile ) ;
}
}
/*
= = = = = = = = = = = = = =
PF_infokey
string ( entity e , string key ) infokey
= = = = = = = = = = = = = =
*/
void PF_infokey ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e ;
int e1 ;
char * value ;
char * key ;
char ov [ 256 ] ;
char * dest ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
e1 = NUM_FOR_EDICT ( prinst , e ) ;
key = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
if ( e1 = = 0 )
{
if ( ( value = Info_ValueForKey ( svs . info , key ) ) = = NULL | | ! * value )
value = Info_ValueForKey ( localinfo , key ) ;
}
else if ( e1 < = MAX_CLIENTS )
{
if ( ! strcmp ( key , " ip " ) )
value = strcpy ( ov , NET_BaseAdrToString ( svs . clients [ e1 - 1 ] . netchan . remote_address ) ) ;
else if ( ! strcmp ( key , " ping " ) )
{
int ping = SV_CalcPing ( & svs . clients [ e1 - 1 ] ) ;
sprintf ( ov , " %d " , ping ) ;
value = ov ;
}
else if ( ! strcmp ( key , " trustlevel " ) ) //info for progs.
{
rankstats_t rs ;
if ( ! svs . clients [ e1 - 1 ] . rankid )
value = " " ;
else if ( Rank_GetPlayerStats ( svs . clients [ e1 - 1 ] . rankid , & rs ) )
{
sprintf ( ov , " %d " , rs . trustlevel ) ;
value = ov ;
}
else
value = " " ;
}
else
value = Info_ValueForKey ( svs . clients [ e1 - 1 ] . userinfo , key ) ;
} else
value = " " ;
2005-05-20 03:32:53 +00:00
dest = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
strcpy ( dest , value ) ;
RETURN_CSTRING ( dest ) ;
}
/*
= = = = = = = = = = = = = =
PF_stof
float ( string s ) stof
= = = = = = = = = = = = = =
*/
void PF_stof ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
G_FLOAT ( OFS_RETURN ) = atof ( s ) ;
}
void PF_Sin ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = sin ( G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Cos ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = cos ( G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_Sqrt ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = sqrt ( G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_pow ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = pow ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
}
/*
= = = = = = = = = = = = = =
PF_multicast
void ( vector where , float set ) multicast
= = = = = = = = = = = = = =
*/
void PF_multicast ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
# if !defined(NQPROT) && !defined(PREPARSE) //these make multicasts issue when message is compleate, making the multicast builtin useless.
float * o ;
int to ;
o = G_VECTOR ( OFS_PARM0 ) ;
to = G_FLOAT ( OFS_PARM1 ) ;
SV_Multicast ( o , to ) ;
# endif
}
2004-11-21 07:31:26 +00:00
static void PF_Fixme ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
int i ;
qboolean printedheader = false ;
SV_EndRedirect ( ) ;
for ( i = 0 ; BuiltinList [ i ] . bifunc ; i + + )
{
if ( BuiltinList [ i ] . ebfsnum = = prinst - > lastcalledbuiltinnumber )
{
if ( ! printedheader )
{
Con_Printf ( " \n Mod forgot to ensure support for builtin %i \n Possible builtins: \n " , prinst - > lastcalledbuiltinnumber ) ;
printedheader = true ;
}
Con_Printf ( " %s \n " , BuiltinList [ i ] . name ) ;
}
}
Con_Printf ( " \n " ) ;
if ( progstype = = PROG_QW )
2005-02-28 07:16:19 +00:00
prinst - > RunError ( prinst , " \n Builtin %i not implemented. \n Mods designed for mvdsv may need pr_imitatemvdsv to be enabled. " , prinst - > lastcalledbuiltinnumber ) ;
2004-08-31 23:58:18 +00:00
else
2005-02-28 07:16:19 +00:00
prinst - > RunError ( prinst , " \n Builtin %i not implemented. \n Mod is not compatable. " , prinst - > lastcalledbuiltinnumber ) ;
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " bulitin not implemented " ) ;
2004-08-23 00:15:46 +00:00
}
2004-08-31 23:58:18 +00:00
void PF_Ignore ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_INT ( OFS_RETURN ) = 0 ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = =
PF_logfrag
logfrag ( killer , killee )
= = = = = = = = = = = = = =
*/
void PF_logstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
s = PF_VarString ( prinst , 0 , pr_globals ) ;
if ( sv_fraglogfile ) {
fprintf ( sv_fraglogfile , s ) ;
fflush ( sv_fraglogfile ) ;
}
}
# define PRSTR 0xa6ffb3d7
void PF_newstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) //mvdsv
{
char * s ;
int len ;
char * in = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
len = strlen ( in ) + 1 ;
if ( * prinst - > callargc = = 2 & & G_FLOAT ( OFS_PARM1 ) > len )
len = G_FLOAT ( OFS_PARM1 ) ;
s = Z_Malloc ( len + 8 ) ;
( ( int * ) s ) [ 0 ] = PRSTR ;
( ( int * ) s ) [ 1 ] = len ;
strcpy ( s + 8 , in ) ;
RETURN_SSTRING ( s + 8 ) ;
}
void PF_dupstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) //frik_file
{
char * s , * in ;
int len ;
in = PF_VarString ( prinst , 0 , pr_globals ) ;
len = strlen ( in ) + 1 ;
s = Z_Malloc ( len + 8 ) ;
( ( int * ) s ) [ 0 ] = PRSTR ;
( ( int * ) s ) [ 1 ] = len ;
strcpy ( s + 8 , in ) ;
RETURN_SSTRING ( s + 8 ) ;
}
void PF_forgetstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
s - = 8 ;
if ( ( ( int * ) s ) [ 0 ] ! = PRSTR )
{
2004-11-21 07:31:26 +00:00
Con_Printf ( " QC tried to free a non allocated string: " ) ;
Con_Printf ( " %s \n " , s + 8 ) ; //two prints, so that logged prints ensure the first is written.
( * prinst - > pr_trace ) = 1 ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-03-28 07:05:38 +00:00
( ( int * ) s ) [ 0 ] = 0xabcd1234 ;
2004-08-23 00:15:46 +00:00
Z_Free ( s ) ;
}
void PF_strlen ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = strlen ( PR_GetStringOfs ( prinst , OFS_PARM0 ) ) ;
}
void PF_strcatp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * buf = PR_GetStringOfs ( prinst , OFS_PARM0 ) ; char * add = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
int wantedlen = G_FLOAT ( OFS_PARM2 ) ;
int len ;
if ( ( ( int * ) ( buf - 8 ) ) [ 0 ] ! = PRSTR )
{
Con_Printf ( " QC tried to add to a non allocated string \n " ) ;
2004-11-21 07:31:26 +00:00
( * prinst - > pr_trace ) = 1 ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = 0 ;
return ;
}
len = strlen ( add ) ;
buf + = strlen ( buf ) ;
strcat ( buf , add ) ;
buf + = len ;
while ( len + + < wantedlen )
* buf + + = ' ' ;
* buf = ' \0 ' ;
G_INT ( OFS_RETURN ) = G_INT ( OFS_PARM0 ) ;
}
void PF_redstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * string = PR_GetStringOfs ( prinst , OFS_PARM0 ) , * s ;
static char buf [ 1024 ] ;
for ( s = buf ; * string ; s + + , string + + )
* s = * string | 128 ;
* s = ' \0 ' ;
RETURN_TSTRING ( buf ) ;
}
# ifdef PEXT_BULLETENS
void PF_bulleten ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int j ;
client_t * client ;
char * msg = PF_VarString ( prinst , 1 , pr_globals ) ;
int board = G_FLOAT ( OFS_PARM0 ) ;
int msglen = strlen ( msg ) ;
// send the data to all relevent clients
for ( j = 0 , client = svs . clients ; j < MAX_CLIENTS ; j + + , client + + )
{
if ( client - > state < cs_connected ) //so a call can be used in client connected.
continue ;
if ( client - > fteprotocolextensions & PEXT_BULLETENS )
{
ClientReliableCheckBlock ( client , msglen + 1 ) ;
ClientReliableWrite_Byte ( client , svc_bulletentext ) ;
ClientReliableWrite_Byte ( client , board ) ;
ClientReliableWrite_String ( client , msg ) ;
}
}
}
# endif
# ifdef SVCHAT
void SV_Chat ( char * filename , float starttag , edict_t * edict ) ;
void PF_chat ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_Chat ( PR_GetStringOfs ( prinst , OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) , G_EDICT ( prinst , OFS_PARM2 ) ) ;
}
# endif
//FRIK_FILE extensions.
//returns a section of a string as a tempstring
void PF_substring ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i , start , length ;
char * s ;
2005-05-20 03:32:53 +00:00
char * string = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
start = G_FLOAT ( OFS_PARM1 ) ;
length = G_FLOAT ( OFS_PARM2 ) ;
2004-11-17 17:52:18 +00:00
if ( start < 0 )
start = strlen ( s ) - start ;
if ( length < 0 )
length = strlen ( s ) - start ;
2004-11-21 21:24:46 +00:00
if ( start > = strlen ( s ) | | length < = 0 | | ! * s )
2004-11-17 17:52:18 +00:00
{
RETURN_TSTRING ( " " ) ;
return ;
}
if ( length > = MAXTEMPBUFFERLEN )
length = MAXTEMPBUFFERLEN - 1 ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < start & & * s ; i + + , s + + )
;
for ( i = 0 ; * s & & i < length ; i + + , s + + )
string [ i ] = * s ;
string [ i ] = 0 ;
RETURN_SSTRING ( string ) ;
}
//vector(string s) stov = #117
//returns vector value from a string
void PF_stov ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
char * s ;
float * out ;
s = PF_VarString ( prinst , 0 , pr_globals ) ;
out = G_VECTOR ( OFS_RETURN ) ;
out [ 0 ] = out [ 1 ] = out [ 2 ] = 0 ;
if ( * s = = ' \' ' )
s + + ;
for ( i = 0 ; i < 3 ; i + + )
{
while ( * s = = ' ' | | * s = = ' \t ' )
s + + ;
out [ i ] = atof ( s ) ;
if ( ! out [ i ] & & * s ! = ' - ' & & * s ! = ' + ' & & ( * s < ' 0 ' | | * s > ' 9 ' ) )
break ; // not a number
while ( * s & & * s ! = ' ' & & * s ! = ' \t ' & & * s ! = ' \' ' )
s + + ;
if ( * s = = ' \' ' )
break ;
}
}
2004-11-17 17:52:18 +00:00
//FTE_STRINGS
//strstr, without generating a new string. Use in conjunction with FRIK_FILE's substring for more similar strstr.
void PF_strstrofs ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * instr = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * match = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
int firstofs = ( * prinst - > callargc > 2 ) ? G_FLOAT ( OFS_PARM1 ) : 0 ;
if ( firstofs & & ( firstofs < 0 | | firstofs > strlen ( instr ) ) )
{
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
match = strstr ( instr + firstofs , match ) ;
if ( ! match )
G_FLOAT ( OFS_RETURN ) = - 1 ;
else
G_FLOAT ( OFS_RETURN ) = match - instr ;
}
2005-04-16 16:21:27 +00:00
//FTE_STRINGS
//returns characture at position X
2004-11-17 17:52:18 +00:00
void PF_str2chr ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * instr = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
int ofs = ( * prinst - > callargc > 1 ) ? G_FLOAT ( OFS_PARM1 ) : 0 ;
if ( ofs < 0 )
ofs = strlen ( instr ) + ofs ;
if ( ofs & & ( ofs < 0 | | ofs > strlen ( instr ) ) )
G_FLOAT ( OFS_RETURN ) = ' \0 ' ;
else
G_FLOAT ( OFS_RETURN ) = instr [ ofs ] ;
}
2005-04-16 16:21:27 +00:00
//FTE_STRINGS
//returns a string containing one characture per parameter (up to the qc max params of 8).
2004-11-17 17:52:18 +00:00
void PF_chr2str ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
2005-05-20 03:32:53 +00:00
char * string = PF_TempStr ( prinst ) ;
2004-11-17 17:52:18 +00:00
for ( i = 0 ; i < * prinst - > callargc ; i + + )
string [ i ] = G_FLOAT ( OFS_PARM0 + i * 3 ) ;
string [ i ] = ' \0 ' ;
RETURN_SSTRING ( string ) ;
}
static int chrconv_number ( int i , int base , int conv )
{
i - = base ;
switch ( conv )
{
default :
case 0 :
break ;
case 1 :
base = ' 0 ' ;
break ;
case 2 :
base = ' 0 ' + 128 ;
break ;
case 3 :
base = ' 0 ' - 30 ;
break ;
case 4 :
base = ' 0 ' + 128 - 30 ;
break ;
}
return i + base ;
}
static int chrconv_punct ( int i , int base , int conv )
{
i - = base ;
switch ( conv )
{
default :
case 0 :
break ;
case 1 :
base = 0 ;
break ;
case 2 :
base = 128 ;
break ;
}
return i + base ;
}
static int chrchar_alpha ( int i , int basec , int baset , int convc , int convt )
{
//convert case and colour seperatly...
i - = baset + basec ;
switch ( convt )
{
default :
case 0 :
break ;
case 1 :
baset = 0 ;
break ;
case 2 :
baset = 128 ;
break ;
}
switch ( convc )
{
default :
case 0 :
break ;
case 1 :
basec = ' a ' ;
break ;
case 2 :
basec = ' A ' ;
break ;
}
return i + basec + baset ;
}
2005-04-16 16:21:27 +00:00
//FTE_STRINGS
//bulk convert a string. change case or colouring.
2004-11-17 17:52:18 +00:00
void PF_strconv ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int ccase = G_FLOAT ( OFS_PARM0 ) ; //0 same, 1 lower, 2 upper
int redalpha = G_FLOAT ( OFS_PARM1 ) ; //0 same, 1 white, 2 red
int redchars = G_FLOAT ( OFS_PARM2 ) ; //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial
2004-12-09 23:46:41 +00:00
unsigned char * string = PF_VarString ( prinst , 3 , pr_globals ) ;
2004-11-17 17:52:18 +00:00
int len = strlen ( string ) ;
int i ;
2005-05-20 03:32:53 +00:00
unsigned char * result = PF_TempStr ( prinst ) ;
2004-11-17 17:52:18 +00:00
if ( len > = MAXTEMPBUFFERLEN )
len = MAXTEMPBUFFERLEN - 1 ;
2005-05-17 02:36:54 +00:00
RETURN_SSTRING ( ( ( char * ) result ) ) ;
2004-11-17 17:52:18 +00:00
for ( i = 0 ; i < len ; i + + , string + + , result + + ) //do this backwards
{
if ( * string > = ' 0 ' & & * string < = ' 9 ' ) //normal numbers...
* result = chrconv_number ( * string , ' 0 ' , redchars ) ;
else if ( * string > = ' 0 ' + 128 & & * string < = ' 9 ' + 128 )
* result = chrconv_number ( * string , ' 0 ' + 128 , redchars ) ;
else if ( * string > = ' 0 ' + 128 - 30 & & * string < = ' 9 ' + 128 - 30 )
* result = chrconv_number ( * string , ' 0 ' + 128 - 30 , redchars ) ;
else if ( * string > = ' 0 ' - 30 & & * string < = ' 9 ' - 30 )
* result = chrconv_number ( * string , ' 0 ' - 30 , redchars ) ;
else if ( * string > = ' a ' & & * string < = ' z ' ) //normal numbers...
* result = chrchar_alpha ( * string , 0 , ' a ' , ccase , redchars ) ;
else if ( * string > = ' A ' & & * string < = ' Z ' ) //normal numbers...
* result = chrchar_alpha ( * string , 0 , ' A ' , ccase , redchars ) ;
else if ( * string > = ' a ' + 128 & & * string < = ' z ' + 128 ) //normal numbers...
* result = chrchar_alpha ( * string , 128 , ' a ' , ccase , redchars ) ;
else if ( * string > = ' A ' + 128 & & * string < = ' Z ' + 128 ) //normal numbers...
* result = chrchar_alpha ( * string , 128 , ' A ' , ccase , redchars ) ;
2004-12-09 23:46:41 +00:00
else if ( ( * string & 127 ) < 16 | | ! redalpha ) //special chars..
2004-11-17 17:52:18 +00:00
* result = * string ;
else if ( * string < 128 )
* result = chrconv_punct ( * string , 0 , redalpha ) ;
else
* result = chrconv_punct ( * string , 128 , redalpha ) ;
}
* result = ' \0 ' ;
}
2005-04-16 16:21:27 +00:00
//FTE_STRINGS
//C style strncmp (compare first n charactures - case sensative. Note that there is no strcmp provided)
void PF_strncmp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * a = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * b = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
float len = G_FLOAT ( OFS_PARM2 ) ;
G_FLOAT ( OFS_RETURN ) = strncmp ( a , b , len ) ;
}
//FTE_STRINGS
//C style strcasecmp (case insensative string compare)
void PF_strcasecmp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * a = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * b = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
G_FLOAT ( OFS_RETURN ) = stricmp ( a , b ) ;
}
//FTE_STRINGS
//C style strncasecmp (compare first n charactures - case insensative)
void PF_strncasecmp ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * a = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * b = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
float len = G_FLOAT ( OFS_PARM2 ) ;
G_FLOAT ( OFS_RETURN ) = strnicmp ( a , b , len ) ;
}
//uses qw style \key\value strings
2004-11-17 17:52:18 +00:00
void PF_infoadd ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * info = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * key = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
char * value = PF_VarString ( prinst , 2 , pr_globals ) ;
char * temp ;
2005-05-20 03:32:53 +00:00
temp = PF_TempStr ( prinst ) ;
2004-12-09 23:46:41 +00:00
Q_strncpyz ( temp , info , MAXTEMPBUFFERLEN ) ;
2004-11-17 17:52:18 +00:00
Info_SetValueForStarKey ( temp , key , value , MAXTEMPBUFFERLEN ) ;
RETURN_SSTRING ( temp ) ;
}
2005-04-16 16:21:27 +00:00
//uses qw style \key\value strings
2004-11-17 17:52:18 +00:00
void PF_infoget ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * info = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * key = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
char * temp ;
key = Info_ValueForKey ( info , key ) ;
2005-05-20 03:32:53 +00:00
temp = PF_TempStr ( prinst ) ;
2004-11-17 17:52:18 +00:00
strcpy ( temp , key ) ;
RETURN_SSTRING ( temp ) ;
}
//back to frik_file support.
2004-08-23 00:15:46 +00:00
# define MAX_QC_FILES 8
2005-02-28 07:16:19 +00:00
# define FIRST_QC_FILE_INDEX 1000
2004-08-23 00:15:46 +00:00
typedef struct {
char name [ 256 ] ;
char * data ;
int bufferlen ;
int len ;
int ofs ;
int accessmode ;
progfuncs_t * prinst ;
} pf_fopen_files_t ;
pf_fopen_files_t pf_fopen_files [ MAX_QC_FILES ] ;
void PF_fopen ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * name = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
int fmode = G_FLOAT ( OFS_PARM1 ) ;
int i ;
for ( i = 0 ; i < MAX_QC_FILES ; i + + )
if ( ! pf_fopen_files [ i ] . data )
break ;
if ( i = = MAX_QC_FILES ) //too many already open
{
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
if ( name [ 1 ] = = ' : ' | | //dos filename absolute path specified - reject.
2004-11-21 07:31:26 +00:00
strchr ( name , ' \\ ' ) | | * name = = ' / ' | | //absolute path was given - reject
2004-08-23 00:15:46 +00:00
strstr ( name , " .. " ) ) //someone tried to be cleaver.
{
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
2004-11-17 17:52:18 +00:00
Q_strncpyz ( pf_fopen_files [ i ] . name , va ( " data/%s " , name ) , sizeof ( pf_fopen_files [ i ] . name ) ) ;
2004-08-23 00:15:46 +00:00
pf_fopen_files [ i ] . accessmode = fmode ;
switch ( fmode )
{
case 0 : //read
2004-11-17 17:52:18 +00:00
pf_fopen_files [ i ] . data = COM_LoadMallocFile ( pf_fopen_files [ i ] . name ) ;
2004-11-21 07:31:26 +00:00
if ( ! pf_fopen_files [ i ] . data )
{
Q_strncpyz ( pf_fopen_files [ i ] . name , name , sizeof ( pf_fopen_files [ i ] . name ) ) ;
pf_fopen_files [ i ] . data = COM_LoadMallocFile ( pf_fopen_files [ i ] . name ) ;
}
2004-08-23 00:15:46 +00:00
if ( pf_fopen_files [ i ] . data )
2005-02-28 07:16:19 +00:00
{
G_FLOAT ( OFS_RETURN ) = i + FIRST_QC_FILE_INDEX ;
pf_fopen_files [ i ] . prinst = prinst ;
}
2004-08-23 00:15:46 +00:00
else
G_FLOAT ( OFS_RETURN ) = - 1 ;
2004-11-21 07:31:26 +00:00
pf_fopen_files [ i ] . bufferlen = pf_fopen_files [ i ] . len = com_filesize ;
pf_fopen_files [ i ] . ofs = 0 ;
2004-08-23 00:15:46 +00:00
break ;
case 1 : //append
2004-11-17 17:52:18 +00:00
pf_fopen_files [ i ] . data = COM_LoadMallocFile ( pf_fopen_files [ i ] . name ) ;
2004-08-23 00:15:46 +00:00
pf_fopen_files [ i ] . ofs = pf_fopen_files [ i ] . bufferlen = pf_fopen_files [ i ] . len = com_filesize ;
if ( pf_fopen_files [ i ] . data )
{
2005-02-28 07:16:19 +00:00
G_FLOAT ( OFS_RETURN ) = i + FIRST_QC_FILE_INDEX ;
pf_fopen_files [ i ] . prinst = prinst ;
2004-08-23 00:15:46 +00:00
break ;
}
2004-11-17 17:52:18 +00:00
//file didn't exist - fall through
2004-08-23 00:15:46 +00:00
case 2 : //write
pf_fopen_files [ i ] . bufferlen = 8192 ;
pf_fopen_files [ i ] . data = BZ_Malloc ( pf_fopen_files [ i ] . bufferlen ) ;
pf_fopen_files [ i ] . len = 0 ;
pf_fopen_files [ i ] . ofs = 0 ;
2005-02-28 07:16:19 +00:00
G_FLOAT ( OFS_RETURN ) = i + FIRST_QC_FILE_INDEX ;
pf_fopen_files [ i ] . prinst = prinst ;
2004-08-23 00:15:46 +00:00
break ;
default : //bad
G_FLOAT ( OFS_RETURN ) = - 1 ;
break ;
}
}
void PF_fclose ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
int fnum = G_FLOAT ( OFS_PARM0 ) - FIRST_QC_FILE_INDEX ;
2004-08-23 00:15:46 +00:00
if ( fnum < 0 | | fnum > = MAX_QC_FILES )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fclose: File out of range \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //out of range
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( ! pf_fopen_files [ fnum ] . data )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fclose: File is not open \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //not open
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( pf_fopen_files [ fnum ] . prinst ! = prinst )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fclose: File is from wrong instance \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //this just isn't ours.
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
switch ( pf_fopen_files [ fnum ] . accessmode )
{
case 0 :
BZ_Free ( pf_fopen_files [ fnum ] . data ) ;
break ;
case 1 :
case 2 :
COM_WriteFile ( pf_fopen_files [ fnum ] . name , pf_fopen_files [ fnum ] . data , pf_fopen_files [ fnum ] . len ) ;
BZ_Free ( pf_fopen_files [ fnum ] . data ) ;
break ;
}
pf_fopen_files [ fnum ] . data = NULL ;
2005-02-28 07:16:19 +00:00
pf_fopen_files [ fnum ] . prinst = NULL ;
2004-08-23 00:15:46 +00:00
}
void PF_fgets ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char c , * s , * o , * max ;
2005-02-28 07:16:19 +00:00
int fnum = G_FLOAT ( OFS_PARM0 ) - FIRST_QC_FILE_INDEX ;
2005-05-20 03:32:53 +00:00
char * pr_string_temp = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
* pr_string_temp = ' \0 ' ;
RETURN_SSTRING ( pr_string_temp ) ;
if ( fnum < 0 | | fnum > = MAX_QC_FILES )
2005-02-28 07:16:19 +00:00
{
2005-03-28 00:11:59 +00:00
PR_BIError ( prinst , " PF_fgets: File out of range \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //out of range
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( ! pf_fopen_files [ fnum ] . data )
2005-02-28 07:16:19 +00:00
{
2005-03-28 00:11:59 +00:00
PR_BIError ( prinst , " PF_fgets: File is not open \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //not open
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( pf_fopen_files [ fnum ] . prinst ! = prinst )
2005-02-28 07:16:19 +00:00
{
2005-03-28 00:11:59 +00:00
PR_BIError ( prinst , " PF_fgets: File is from wrong instance \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //this just isn't ours.
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
//read up to the next \n, ignoring any \rs.
o = pr_string_temp ;
2004-11-21 07:31:26 +00:00
max = o + MAXTEMPBUFFERLEN - 1 ;
2004-08-23 00:15:46 +00:00
s = pf_fopen_files [ fnum ] . data + pf_fopen_files [ fnum ] . ofs ;
while ( * s )
{
c = * s + + ;
if ( c = = ' \n ' )
break ;
if ( c = = ' \r ' )
continue ;
if ( o = = max )
break ;
* o + + = c ;
}
* o = ' \0 ' ;
pf_fopen_files [ fnum ] . ofs = s - pf_fopen_files [ fnum ] . data ;
2004-11-17 17:52:18 +00:00
if ( ! pr_string_temp [ 0 ] & & ! * s )
2004-12-08 04:14:52 +00:00
G_INT ( OFS_RETURN ) = 0 ; //EOF
2004-11-17 17:52:18 +00:00
else
2005-05-15 18:49:04 +00:00
G_INT ( OFS_RETURN ) = pr_string_temp - prinst - > stringtable ;
2004-08-23 00:15:46 +00:00
}
void PF_fputs ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-02-28 07:16:19 +00:00
int fnum = G_FLOAT ( OFS_PARM0 ) - FIRST_QC_FILE_INDEX ;
2004-08-23 00:15:46 +00:00
char * msg = PF_VarString ( prinst , 1 , pr_globals ) ;
int len = strlen ( msg ) ;
if ( fnum < 0 | | fnum > = MAX_QC_FILES )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fgets: File out of range \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //out of range
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( ! pf_fopen_files [ fnum ] . data )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fgets: File is not open \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //not open
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( pf_fopen_files [ fnum ] . prinst ! = prinst )
2005-02-28 07:16:19 +00:00
{
Con_Printf ( " PF_fgets: File is from wrong instance \n " ) ;
2004-08-23 00:15:46 +00:00
return ; //this just isn't ours.
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
if ( pf_fopen_files [ fnum ] . bufferlen < pf_fopen_files [ fnum ] . ofs + len )
{
char * newbuf ;
pf_fopen_files [ fnum ] . bufferlen = pf_fopen_files [ fnum ] . bufferlen * 2 + len ;
newbuf = BZF_Malloc ( pf_fopen_files [ fnum ] . bufferlen ) ;
memcpy ( newbuf , pf_fopen_files [ fnum ] . data , pf_fopen_files [ fnum ] . len ) ;
BZ_Free ( pf_fopen_files [ fnum ] . data ) ;
pf_fopen_files [ fnum ] . data = newbuf ;
}
memcpy ( pf_fopen_files [ fnum ] . data + pf_fopen_files [ fnum ] . ofs , msg , len ) ;
if ( pf_fopen_files [ fnum ] . len < pf_fopen_files [ fnum ] . ofs + len )
pf_fopen_files [ fnum ] . len = pf_fopen_files [ fnum ] . ofs + len ;
pf_fopen_files [ fnum ] . ofs + = len ;
}
void PF_fcloseall ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
for ( i = 0 ; i < MAX_QC_FILES ; i + + )
{
2004-11-21 07:31:26 +00:00
if ( pf_fopen_files [ i ] . prinst ! = prinst )
continue ;
2005-02-28 07:16:19 +00:00
G_FLOAT ( OFS_PARM0 ) = i + FIRST_QC_FILE_INDEX ;
2004-08-23 00:15:46 +00:00
PF_fclose ( prinst , pr_globals ) ;
}
}
2005-04-16 16:21:27 +00:00
typedef struct prvmsearch_s {
int handle ;
progfuncs_t * fromprogs ; //share across menu/server
int entries ;
char * * names ;
int * sizes ;
struct prvmsearch_s * next ;
} prvmsearch_t ;
prvmsearch_t * prvmsearches ;
int prvm_nextsearchhandle ;
void search_close ( progfuncs_t * prinst , int handle )
{
int i ;
prvmsearch_t * prev , * s ;
prev = NULL ;
for ( s = prvmsearches ; s ; )
{
if ( s - > handle = = handle )
{ //close it down.
if ( s - > fromprogs ! = prinst )
{
Con_Printf ( " Handle wasn't valid with that progs \n " ) ;
return ;
}
if ( prev )
prev - > next = s - > next ;
else
prvmsearches = s - > next ;
for ( i = 0 ; i < s - > entries ; i + + )
{
BZ_Free ( s - > names [ i ] ) ;
}
BZ_Free ( s - > names ) ;
BZ_Free ( s - > sizes ) ;
BZ_Free ( s ) ;
return ;
}
prev = s ;
s = s - > next ;
}
}
//a progs was closed... hunt down it's searches, and warn about any searches left open.
void search_close_progs ( progfuncs_t * prinst , qboolean complain )
{
int i ;
prvmsearch_t * prev , * s ;
prev = NULL ;
for ( s = prvmsearches ; s ; )
{
if ( s - > fromprogs = = prinst )
{ //close it down.
if ( complain )
Con_Printf ( " Warning: Progs search was still active \n " ) ;
if ( prev )
prev - > next = s - > next ;
else
prvmsearches = s - > next ;
for ( i = 0 ; i < s - > entries ; i + + )
{
BZ_Free ( s - > names [ i ] ) ;
}
BZ_Free ( s - > names ) ;
BZ_Free ( s - > sizes ) ;
BZ_Free ( s ) ;
if ( prev )
s = prev - > next ;
else
s = prvmsearches ;
continue ;
}
prev = s ;
s = s - > next ;
}
if ( ! prvmsearches )
prvm_nextsearchhandle = 0 ; //might as well.
}
int search_enumerate ( char * name , int fsize , void * parm )
{
prvmsearch_t * s = parm ;
s - > names = BZ_Realloc ( s - > names , ( ( s - > entries + 64 ) & ~ 63 ) * sizeof ( char * ) ) ;
s - > sizes = BZ_Realloc ( s - > sizes , ( ( s - > entries + 64 ) & ~ 63 ) * sizeof ( int ) ) ;
s - > names [ s - > entries ] = BZ_Malloc ( strlen ( name ) + 1 ) ;
strcpy ( s - > names [ s - > entries ] , name ) ;
s - > sizes [ s - > entries ] = fsize ;
s - > entries + + ;
return true ;
}
//float search_begin(string pattern, float caseinsensitive, float quiet) = #74;
void PF_search_begin ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{ //< 0 for error, > 0 for handle.
char * pattern = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
// qboolean caseinsensative = G_FLOAT(OFS_PARM1);
// qboolean quiet = G_FLOAT(OFS_PARM2);
prvmsearch_t * s ;
s = BZ_Malloc ( sizeof ( * s ) ) ;
s - > fromprogs = prinst ;
s - > handle = prvm_nextsearchhandle + + ;
COM_EnumerateFiles ( pattern , search_enumerate , s ) ;
if ( s - > entries = = 0 )
{
BZ_Free ( s ) ;
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
s - > next = prvmsearches ;
prvmsearches = s ;
G_FLOAT ( OFS_RETURN ) = s - > handle ;
}
//void search_end(float handle) = #75;
void PF_search_end ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int handle = G_FLOAT ( OFS_PARM0 ) ;
search_close ( prinst , handle ) ;
}
//float search_getsize(float handle) = #76;
void PF_search_getsize ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int handle = G_FLOAT ( OFS_PARM0 ) ;
prvmsearch_t * s ;
G_FLOAT ( OFS_RETURN ) = - 1 ;
for ( s = prvmsearches ; s ; s = s - > next )
{
if ( s - > handle = = handle )
{ //close it down.
if ( s - > fromprogs ! = prinst )
{
Con_Printf ( " Handle wasn't valid with that progs \n " ) ;
return ;
}
G_FLOAT ( OFS_RETURN ) = s - > entries ;
return ;
}
}
}
//string search_getfilename(float handle, float num) = #77;
void PF_search_getfilename ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int handle = G_FLOAT ( OFS_PARM0 ) ;
int num = G_FLOAT ( OFS_PARM1 ) ;
prvmsearch_t * s ;
G_INT ( OFS_RETURN ) = 0 ;
for ( s = prvmsearches ; s ; s = s - > next )
{
if ( s - > handle = = handle )
{ //close it down.
if ( s - > fromprogs ! = prinst )
{
Con_Printf ( " Search handle wasn't valid with that progs \n " ) ;
return ;
}
if ( num < 0 | | num > = s - > entries )
return ;
G_INT ( OFS_RETURN ) = ( int ) ( s - > names [ num ] - prinst - > stringtable ) ;
return ;
}
}
Con_Printf ( " Search handle wasn't valid \n " ) ;
}
//closes filesystem type stuff for when a progs has stopped needing it.
void PR_fclose_progs ( progfuncs_t * prinst )
2004-11-21 07:31:26 +00:00
{
PF_fcloseall ( prinst , PR_globals ( prinst , PR_CURRENT ) ) ;
2005-04-16 16:21:27 +00:00
search_close_progs ( prinst , true ) ;
2004-11-21 07:31:26 +00:00
}
2004-08-23 00:15:46 +00:00
//the lh extension system asks for a name for the extension.
//the ebfs version is a function that returns a builtin number.
//thus lh's system requires various builtins to exist at specific numbers.
typedef struct lh_extension_s {
char * name ;
int numbuiltins ;
qboolean * enabled ;
2004-11-17 17:52:18 +00:00
char * builtins [ 18 ] ; //extend freely
2004-08-23 00:15:46 +00:00
} lh_extension_t ;
lh_extension_t QSG_Extensions [ ] = {
2004-11-17 17:52:18 +00:00
{ " DP_CON_SET " } ,
# ifndef SERVERONLY
{ " DP_CON_SETA " } , //because the server doesn't write configs.
# endif
2004-10-10 06:32:29 +00:00
{ " DP_EF_BLUE " } , //hah!! This is QuakeWorld!!!
{ " DP_EF_FULLBRIGHT " } , //Rerouted to hexen2 support.
2005-05-15 18:49:04 +00:00
{ " DP_EF_NODRAW " } , //implemented by sending it with no modelindex
2004-10-10 06:32:29 +00:00
{ " DP_EF_RED " } ,
2004-08-23 00:15:46 +00:00
{ " DP_HALFLIFE_MAP_CVAR " } ,
2004-10-13 06:37:44 +00:00
{ " DP_MONSTERWALK " } ,
2004-10-10 06:32:29 +00:00
{ " DP_MOVETYPEBOUNCEMISSILE " } , //I added the code for hexen2 support.
{ " DP_MOVETYPEFOLLOW " } ,
2004-10-14 13:08:09 +00:00
{ " DP_QC_CHANGEPITCH " , 1 , NULL , { " changepitch " } } ,
2004-10-10 06:32:29 +00:00
{ " DP_QC_COPYENTITY " , 1 , NULL , { " copyentity " } } ,
2004-09-13 02:22:02 +00:00
{ " DP_QC_CVAR_STRING " , 1 , NULL , { " dp_cvar_string " } } , //448 builtin.
2004-11-17 17:52:18 +00:00
{ " DP_QC_DROPCLIENT " , 1 , NULL , { " dropclient " } } , //453 builtin.
2004-10-10 06:32:29 +00:00
{ " DP_QC_ETOS " , 1 , NULL , { " etos " } } ,
{ " DP_QC_FINDCHAIN " , 1 , NULL , { " findchain " } } ,
{ " DP_QC_FINDCHAINFLOAT " , 1 , NULL , { " findchainfloat " } } ,
2004-10-13 06:37:44 +00:00
{ " DP_QC_FINDFLAGS " , 1 , NULL , { " findflags " } } ,
{ " DP_QC_FINDCHAINFLAGS " , 1 , NULL , { " findchainflags " } } ,
2004-10-10 06:32:29 +00:00
{ " DP_QC_FINDFLOAT " , 1 , NULL , { " findfloat " } } ,
2005-05-20 03:32:53 +00:00
{ " DP_QC_FS_SEARCH " , 4 , NULL , { " search_begin " , " search_end " , " search_getsize " , " search_getfilename " } } ,
2004-08-23 00:15:46 +00:00
{ " DP_QC_MINMAXBOUND " , 3 , NULL , { " min " , " max " , " bound " } } ,
2004-10-14 13:08:09 +00:00
{ " DP_QC_MULTIPLETEMPSTRINGS " } ,
2004-08-23 00:15:46 +00:00
{ " DP_QC_RANDOMVEC " , 1 , NULL , { " randomvec " } } ,
2004-10-10 06:32:29 +00:00
{ " DP_QC_SINCOSSQRTPOW " , 4 , NULL , { " sin " , " cos " , " sqrt " , " pow " } } ,
{ " DP_QC_TRACEBOX " , 1 , NULL , { " tracebox " } } ,
{ " DP_QC_TRACE_MOVETYPES " } , //this one is just a lame excuse to add annother extension...
2004-08-23 00:15:46 +00:00
{ " DP_QC_VECTORVECTORS " , 1 , NULL , { " vectorvectors " } } ,
{ " DP_QUAKE2_MODEL " } ,
{ " DP_QUAKE3_MODEL " } ,
2004-10-10 06:32:29 +00:00
{ " DP_REGISTERCVAR " , 1 , NULL , { " registercvar " } } ,
{ " DP_SPRITE32 " } , //hmm... is it legal to advertise this one?
{ " DP_SV_DRAWONLYTOCLIENT " } ,
{ " DP_SV_NODRAWTOCLIENT " } , //I prefer my older system. Guess I might as well remove that older system at some point.
2004-08-23 00:15:46 +00:00
{ " DP_SV_PLAYERPHYSICS " } ,
2004-10-10 06:32:29 +00:00
{ " DP_SV_SETCOLOR " } ,
{ " DP_TE_BLOOD " , 1 , NULL , { " te_blood " } } ,
2004-11-20 00:55:29 +00:00
{ " DP_TE_BLOODSHOWER " , 1 , NULL , { " te_bloodshower " } } ,
{ " DP_TE_CUSTOMFLASH " , 1 , NULL , { " te_customflash " } } ,
{ " DP_TE_PARTICLECUBE " , 1 , NULL , { " te_particlecube " } } ,
2004-11-21 07:31:26 +00:00
{ " DP_TE_PLASMABURN " , 1 , NULL , { " te_plasmaburn " } } ,
2004-11-20 00:55:29 +00:00
{ " DP_TE_SMALLFLASH " , 1 , NULL , { " te_smallflash " } } ,
{ " DP_TE_SPARK " , 1 , NULL , { " te_spark " } } ,
{ " DP_TE_STANDARDEFFECTBUILTINS " , 14 , NULL , { " te_gunshot " , " te_spike " , " te_superspike " , " te_explosion " , " te_tarexplosion " , " te_wizspike " , " te_knightspike " , " te_lavasplash " , " te_teleport " , " te_explosion2 " , " te_lightning1 " , " te_lightning2 " , " te_lightning3 " , " te_beam " } } , //should we include QW ones?...
2004-09-04 17:52:32 +00:00
{ " EXT_DIMENSION_VISIBILITY " } ,
{ " EXT_DIMENSION_PHYSICS " } ,
{ " EXT_DIMENSION_GHOST " } ,
{ " EXT_BITSHIFT " , 1 , NULL , { " bitshift " } } ,
2004-10-10 06:32:29 +00:00
{ " FRIK_FILE " , 11 , NULL , { " stof " , " fopen " , " fclose " , " fgets " , " fputs " , " strlen " , " strcat " , " substring " , " stov " , " strzone " , " strunzone " } } ,
2004-11-17 17:52:18 +00:00
{ " FTE_CALLTIMEOFDAY " , 1 , NULL , { " calltimeofday " } } ,
2004-08-23 00:15:46 +00:00
{ " FTE_FORCEINFOKEY " , 1 , NULL , { " forceinfokey " } } ,
2005-04-16 16:21:27 +00:00
{ " FTE_ISBACKBUFFERED " , 1 , NULL , { " isbackbuffered " } } ,
2004-10-10 06:32:29 +00:00
# ifndef NOMEDIA
{ " FTE_MEDIA_AVI " } , //playfilm supports avi files.
{ " FTE_MEDIA_CIN " } , //playfilm command supports q2 cin files.
{ " FTE_MEDIA_ROQ " } , //playfilm command supports q3 roq files
# endif
{ " FTE_MULTIPROGS " } , //multiprogs functions are available.
2004-08-23 00:15:46 +00:00
{ " FTE_MULTITHREADED " , 3 , NULL , { " sleep " , " fork " , " abort " } } ,
2004-10-10 06:32:29 +00:00
{ " FTE_MVD_PLAYBACK " } ,
2004-08-23 00:15:46 +00:00
# ifdef SVCHAT
2004-08-31 23:58:18 +00:00
{ " FTE_NPCCHAT " , 1 , NULL , { " chat " } } , //server looks at chat files. It automagically branches through calling qc functions as requested.
2004-08-23 00:15:46 +00:00
# endif
2004-10-10 06:32:29 +00:00
{ " FTE_SOLID_LADDER " } , //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20)
2004-11-17 17:52:18 +00:00
//eperimental advanced strings functions.
//reuses the FRIK_FILE builtins (with substring extension)
{ " FTE_STRINGS " , 18 , NULL , { " stof " , " strlen " , " strcat " , " substring " , " stov " , " strzone " , " strunzone " ,
" strstrofs " , " str2chr " , " chr2str " , " strconv " , " infoadd " , " infoget " , " strncmp " , " strcasecmp " , " strncasecmp " } } ,
2005-05-26 12:55:34 +00:00
{ " HYDR_WRITESTRING2 " , 1 , NULL , { " writestring2 " } } ,
2004-10-10 06:32:29 +00:00
{ " KRIMZON_SV_PARSECLIENTCOMMAND " , 3 , NULL , { " clientcommand " , " tokenize " , " argv " } } , //very very similar to the mvdsv system.
{ " QSG_CVARSTRING " , 1 , NULL , { " cvar_string " } } ,
{ " QW_ENGINE " } , //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ.
{ " QWE_MVD_RECORD " } , //Quakeworld extended get the credit for this one. (mvdsv)
{ " TEI_MD3_MODEL " } ,
2004-10-13 06:37:44 +00:00
// {"TQ_RAILTRAIL"}, //treat this as the ZQ style railtrails which the client already supports, okay so the preparse stuff needs strengthening.
2004-10-10 06:32:29 +00:00
{ " ZQ_MOVETYPE_FLY " } ,
{ " ZQ_MOVETYPE_NOCLIP " } ,
2004-10-14 13:08:09 +00:00
{ " ZQ_MOVETYPE_NONE " }
2005-02-28 07:16:19 +00:00
// {"ZQ_QC_PARTICLE"} //particle builtin works in QW ( we don't mimic ZQ fully though)
2004-08-23 00:15:46 +00:00
} ;
//some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available.
//(which is why there are two lists of extensions here)
2005-02-28 07:16:19 +00:00
//note: not all of these are actually supported. This list mearly reflects the values of the PEXT_ constants.
//Check protocol.h to make sure that the related PEXT is enabled. The engine will only accept if they are actually supported.
2004-08-23 00:15:46 +00:00
lh_extension_t FTE_Protocol_Extensions [ ] =
{
{ " FTE_PEXT_SETVIEW " } , //nq setview works.
{ " DP_ENT_SCALE " } , //entities may be rescaled
{ " FTE_PEXT_LIGHTSTYLECOL " } , //lightstyles may have colours.
{ " DP_ENT_ALPHA " } , //transparent entites
{ " FTE_PEXT_VIEW2 " } , //secondary view.
{ " FTE_PEXT_BULLETENS " } , //bulleten boards (scrolling text on walls)
{ " FTE_PEXT_ZLIBDL " } , //supposed download optimisation (unimportant to qc)
{ " FTE_PEXT_LIGHTUPDATES " } , //zap.mdl is sent as a nail packet.
{ " FTE_PEXT_FATNESS " } , //entities may be expanded along thier vertex normals
{ " DP_HALFLIFE_MAP " } , //entitiy can visit a hl bsp
{ " FTE_PEXT_TE_BULLET " } , //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE
{ " FTE_PEXT_HULLSIZE " } , //means we can tell a client to go to crouching hull
{ " FTE_PEXT_MODELDBL " } , //max of 512 models
{ " FTE_PEXT_ENTITYDBL " } , //max of 1024 ents
{ " FTE_PEXT_ENTITYDBL2 " } , //max of 2048 ents
{ " FTE_PEXT_ORIGINDBL " } , //-8k to +8k map size.
{ " FTE_PEXT_VWEAP " } ,
{ " FTE_PEXT_Q2BSP " } , //supports q2 maps. No bugs are apparent.
2004-08-31 23:58:18 +00:00
{ " FTE_PEXT_Q3BSP " } , //quake3 bsp support. dp probably has an equivelent, but this is queryable per client.
2004-08-23 00:15:46 +00:00
{ " UDC_EXTEFFECT " , 0 , & pr_udc_exteffect_enabled } , //hmm. crap.
2004-08-31 23:58:18 +00:00
{ NULL } , //splitscreen - not queryable.
2004-08-23 00:15:46 +00:00
{ " FTE_HEXEN2 " } , //client can use hexen2 maps. server can use hexen2 progs
{ " FTE_PEXT_SPAWNSTATIC " } , //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatable - previous system failed with -1 skins)
2004-08-31 23:58:18 +00:00
{ " FTE_PEXT_CUSTOMTENTS " , 2 , NULL , { " RegisterTempEnt " , " CustomTempEnt " } } ,
2004-12-19 04:37:42 +00:00
{ " FTE_PEXT_256PACKETENTITIES " } , //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity).
2005-02-28 07:16:19 +00:00
{ " FTE_PEXT_64PLAYERS " } ,
{ " TEI_SHOWLMP2 " , 6 , NULL , { " showpic " , " hidepic " , " movepic " , " changepic " , " showpicent " , " hidepicent " } } , //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered)
{ " DP_GFX_QUAKE3MODELTAGS " , 1 , NULL , { " setattachment " } } ,
{ " FTE_PK3DOWNLOADS " } ,
{ " PEXT_CHUNKEDDOWNLOADS " } ,
{ " EXT_CSQC " }
2004-08-23 00:15:46 +00:00
} ;
2004-09-13 02:22:02 +00:00
int PR_EnableEBFSBuiltin ( char * name , int binum )
2004-08-23 00:15:46 +00:00
{
int i ;
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
if ( ! strcmp ( BuiltinList [ i ] . name , name ) )
{
2004-09-13 02:22:02 +00:00
if ( ! binum )
binum = BuiltinList [ i ] . ebfsnum ;
2004-08-23 00:15:46 +00:00
if ( ! pr_overridebuiltins . value )
{
2004-09-13 02:22:02 +00:00
if ( pr_builtin [ binum ] ! = NULL & & pr_builtin [ binum ] ! = PF_Fixme )
2004-08-23 00:15:46 +00:00
{
2004-09-13 02:22:02 +00:00
if ( pr_builtin [ binum ] = = BuiltinList [ i ] . bifunc ) //it is already this function.
return binum ;
2004-08-23 00:15:46 +00:00
return 0 ; //already used... ?
}
}
2004-09-13 02:22:02 +00:00
pr_builtin [ binum ] = BuiltinList [ i ] . bifunc ;
2004-08-23 00:15:46 +00:00
2004-09-13 02:22:02 +00:00
return binum ;
2004-08-23 00:15:46 +00:00
}
}
return 0 ; //not known
}
lh_extension_t * checkfteextensioncl ( int mask , char * name ) //true if the cient extension mask matches an extension name
{
int i ;
unsigned int m = 1 ;
for ( i = 0 ; i < sizeof ( FTE_Protocol_Extensions ) / sizeof ( lh_extension_t ) ; i + + )
{
2005-02-28 07:16:19 +00:00
if ( mask & ( 1 < < i ) ) //suported
2004-08-23 00:15:46 +00:00
{
if ( FTE_Protocol_Extensions [ i ] . name ) //some were removed
if ( ! stricmp ( name , FTE_Protocol_Extensions [ i ] . name ) ) //name matches
return & FTE_Protocol_Extensions [ i ] ;
}
}
return NULL ;
}
lh_extension_t * checkfteextensionsv ( char * name ) //true if the server supports an protocol extension.
{
int i ;
for ( i = 0 ; i < sizeof ( FTE_Protocol_Extensions ) / sizeof ( lh_extension_t ) ; i + + )
{
2005-02-28 07:16:19 +00:00
if ( svs . fteprotocolextensions & ( 1 < < i ) )
{
if ( FTE_Protocol_Extensions [ i ] . name ) //some were removed
if ( ! stricmp ( name , FTE_Protocol_Extensions [ i ] . name ) ) //name matches
return & FTE_Protocol_Extensions [ i ] ;
}
2004-08-23 00:15:46 +00:00
}
return NULL ;
}
lh_extension_t * checkextension ( char * name )
{
int i ;
for ( i = 0 ; i < sizeof ( QSG_Extensions ) / sizeof ( lh_extension_t ) ; i + + )
{
if ( ! QSG_Extensions [ i ] . name )
continue ;
if ( ! stricmp ( name , QSG_Extensions [ i ] . name ) )
return & QSG_Extensions [ i ] ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = =
PF_checkextension
returns true if the extension is supported by the server
checkextension ( string extensionname , [ entity client ] )
= = = = = = = = = = = = = = = = =
*/
void PF_checkextension ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
lh_extension_t * ext = NULL ;
char * s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
ext = checkextension ( s ) ;
if ( ! ext )
{
if ( * svprogfuncs - > callargc = = 2 )
{
int clnum = NUM_FOR_EDICT ( prinst , G_EDICT ( prinst , OFS_PARM1 ) ) ;
if ( clnum > = 1 & & clnum < = MAX_CLIENTS ) //valid client as second parameter
{
ext = checkfteextensioncl ( svs . clients [ clnum - 1 ] . fteprotocolextensions , s ) ;
}
else if ( clnum = = 0 )
ext = checkfteextensionsv ( s ) ;
else
{
//ent wasn't valid
Con_Printf ( " PF_CheckExtension with invalid client number " ) ;
}
}
else
{
ext = checkfteextensionsv ( s ) ;
}
}
if ( ext )
{
int i ;
G_FLOAT ( OFS_RETURN ) = false ;
for ( i = 0 ; i < ext - > numbuiltins ; i + + )
{
2004-09-13 02:22:02 +00:00
if ( ! PR_EnableEBFSBuiltin ( ext - > builtins [ i ] , 0 ) )
2004-08-23 00:15:46 +00:00
{
Con_Printf ( " Failed to initialise builtin \" %s \" for extension \" %s \" " , ext - > builtins [ i ] , s ) ;
return ; //whoops, we failed.
}
}
if ( ext - > enabled )
* ext - > enabled = true ;
G_FLOAT ( OFS_RETURN ) = true ;
2005-02-28 07:16:19 +00:00
Con_Printf ( " Extension %s is supported \n " , s ) ;
2004-08-23 00:15:46 +00:00
}
else
G_FLOAT ( OFS_RETURN ) = false ;
}
void PF_builtinsupported ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
2004-09-13 02:22:02 +00:00
G_FLOAT ( OFS_RETURN ) = PR_EnableEBFSBuiltin ( s , 0 ) ;
2004-08-23 00:15:46 +00:00
}
//mvdsv builtins.
void PF_ExecuteCommand ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) / / 83 / / void ( ) exec ;
{
int old_other , old_self ; // mod_consolecmd will be executed, so we need to store this
old_self = pr_global_struct - > self ;
old_other = pr_global_struct - > other ;
Cbuf_Execute ( ) ;
pr_global_struct - > self = old_self ;
pr_global_struct - > other = old_other ;
}
2004-11-17 17:52:18 +00:00
void PF_ArgC ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) / / 85 / / float ( ) argc ;
2004-08-23 00:15:46 +00:00
{
G_FLOAT ( OFS_RETURN ) = Cmd_Argc ( ) ;
}
2004-11-17 17:52:18 +00:00
//KRIMZON_SV_PARSECLIENTCOMMAND added these two.
void PF_Tokenize ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) / / 84 / / void ( string str ) tokanize ;
2004-08-23 00:15:46 +00:00
{
2004-12-08 04:14:52 +00:00
Cmd_TokenizeString ( PR_GetStringOfs ( prinst , OFS_PARM0 ) , false , true ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = Cmd_Argc ( ) ;
}
void PF_ArgV ( progfuncs_t * prinst , struct globalvars_s * pr_globals ) / / 86 / / string ( float num ) argv ;
{
2005-05-20 03:32:53 +00:00
char * dest = PF_TempStr ( prinst ) ;
2005-04-16 16:21:27 +00:00
int i = G_FLOAT ( OFS_PARM0 ) ;
if ( i < 0 )
{
PR_BIError ( prinst , " pr_argv with i < 0 " ) ;
G_INT ( OFS_RETURN ) = 0 ;
return ;
}
strcpy ( dest , Cmd_Argv ( i ) ) ;
2004-08-23 00:15:46 +00:00
RETURN_CSTRING ( dest ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_teamfield
string teamfield ( . string field )
= = = = = = = = = = = = = = = = =
*/
void PF_teamfield ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
pr_teamfield = G_INT ( OFS_PARM0 ) + prinst - > fieldadjust ;
}
/*
= = = = = = = = = = = = = = = = =
PF_substr
string substr ( string str , float start , float len )
= = = = = = = = = = = = = = = = =
*/
void PF_substr ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-20 03:32:53 +00:00
char * dest = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
char * s ;
int start , len , l ;
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
start = ( int ) G_FLOAT ( OFS_PARM1 ) ;
len = ( int ) G_FLOAT ( OFS_PARM2 ) ;
l = strlen ( s ) ;
if ( start > = l | | ! len | | ! * s )
{
RETURN_TSTRING ( " " ) ;
return ;
}
s + = start ;
l - = start ;
if ( len > l + 1 )
len = l + 1 ;
Q_strncpyz ( dest , s , len + 1 ) ;
RETURN_TSTRING ( dest ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_strcat
string strcat ( string str1 , string str2 )
= = = = = = = = = = = = = = = = =
*/
void PF_strcat ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-20 03:32:53 +00:00
char * dest = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
char * src = PF_VarString ( prinst , 0 , pr_globals ) ;
2004-09-13 02:22:02 +00:00
Q_strncpyz ( dest , src , MAXTEMPBUFFERLEN ) ;
2004-08-23 00:15:46 +00:00
RETURN_TSTRING ( dest ) ;
}
2005-03-07 08:55:30 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_strpad
string strcat ( float pad , string str1 , . . . )
= = = = = = = = = = = = = = = = =
*/
void PF_strpad ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-20 03:32:53 +00:00
char * dest = PF_TempStr ( prinst ) ;
2005-03-07 08:55:30 +00:00
int pad = G_FLOAT ( OFS_PARM0 ) ;
char * src = PF_VarString ( prinst , 1 , pr_globals ) ;
RETURN_TSTRING ( dest ) ;
if ( pad < 0 )
{ //pad left
pad = - pad - strlen ( src ) ;
if ( pad > = MAXTEMPBUFFERLEN )
pad = MAXTEMPBUFFERLEN - 1 ;
if ( pad < 0 )
pad = 0 ;
Q_strncpyz ( dest + pad , src , MAXTEMPBUFFERLEN - pad ) ;
while ( pad )
{
pad - - ;
dest [ pad ] = ' ' ;
}
}
else
{ //pad right
if ( pad > = MAXTEMPBUFFERLEN )
pad = MAXTEMPBUFFERLEN - 1 ;
pad - = strlen ( src ) ;
if ( pad < 0 )
pad = 0 ;
Q_strncpyz ( dest , src , MAXTEMPBUFFERLEN ) ;
dest + = strlen ( dest ) ;
while ( pad )
* dest + + = ' ' ;
* dest = ' \0 ' ;
}
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_str2byte
float str2byte ( string str )
= = = = = = = = = = = = = = = = =
*/
void PF_str2byte ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = ( float ) * PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_str2short
float str2short ( string str )
= = = = = = = = = = = = = = = = =
*/
void PF_str2short ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
G_FLOAT ( OFS_RETURN ) = ( float ) LittleShort ( * ( short * ) PR_GetStringOfs ( prinst , OFS_PARM0 ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_readcmd
string readmcmd ( string str )
= = = = = = = = = = = = = = = = =
*/
void PF_readcmd ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
static char output [ 8000 ] ;
extern char outputbuf [ ] ;
extern redirect_t sv_redirected ;
2005-01-16 00:59:48 +00:00
extern int sv_redirectedlang ;
2004-08-23 00:15:46 +00:00
redirect_t old ;
2005-01-16 00:59:48 +00:00
int oldl ;
2004-08-23 00:15:46 +00:00
s = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
Cbuf_Execute ( ) ;
Cbuf_AddText ( s , RESTRICT_LOCAL ) ;
old = sv_redirected ;
2005-01-16 00:59:48 +00:00
oldl = sv_redirectedlang ;
2004-08-23 00:15:46 +00:00
if ( old ! = RD_NONE )
SV_EndRedirect ( ) ;
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( RD_OBLIVION , LANGDEFAULT ) ;
2004-08-23 00:15:46 +00:00
Cbuf_Execute ( ) ;
Q_strncpyz ( output , outputbuf , sizeof ( output ) ) ;
SV_EndRedirect ( ) ;
if ( old ! = RD_NONE )
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( old , oldl ) ;
2004-08-23 00:15:46 +00:00
G_INT ( OFS_RETURN ) = ( int ) PR_SetString ( prinst , output ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_redirectcmd
void redirectcmd ( entity to , string str )
= = = = = = = = = = = = = = = = =
*/
/*
void PF_redirectcmd ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
int entnum ;
extern redirect_t sv_redirected ;
if ( sv_redirected )
return ;
entnum = G_EDICTNUM ( OFS_PARM0 ) ;
if ( entnum < 1 | | entnum > MAX_CLIENTS )
PR_RunError ( " Parm 0 not a client " ) ;
s = G_STRING ( OFS_PARM1 ) ;
Cbuf_AddText ( s ) ;
SV_BeginRedirect ( RD_MOD + entnum ) ;
Cbuf_Execute ( ) ;
SV_EndRedirect ( ) ;
} */
void PF_calltimeofday ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
date_t date ;
func_t f ;
2005-05-20 03:32:53 +00:00
char * ret = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
f = PR_FindFunction ( svprogfuncs , " timeofday " , PR_ANY ) ;
if ( f )
{
SV_TimeOfDay ( & date ) ;
G_FLOAT ( OFS_PARM0 ) = ( float ) date . sec ;
G_FLOAT ( OFS_PARM1 ) = ( float ) date . min ;
G_FLOAT ( OFS_PARM2 ) = ( float ) date . hour ;
G_FLOAT ( OFS_PARM3 ) = ( float ) date . day ;
G_FLOAT ( OFS_PARM4 ) = ( float ) date . mon ;
G_FLOAT ( OFS_PARM5 ) = ( float ) date . year ;
2005-01-18 15:49:57 +00:00
strcpy ( ret , date . str ) ;
G_INT ( OFS_PARM6 ) = ( int ) PR_SetString ( prinst , ret ) ;
2004-08-23 00:15:46 +00:00
PR_ExecuteProgram ( prinst , f ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
PF_forcedemoframe
void PF_forcedemoframe ( float now )
Forces demo frame
if argument ' now ' is set , frame is written instantly
= = = = = = = = = = = = = = = = =
*/
void PF_forcedemoframe ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
demo . forceFrame = 1 ;
// if (G_FLOAT(OFS_PARM0) == 1)
// SV_SendDemoMessage();
}
/*
= = = = = = = = = = = = = = = = =
PF_strcpy
void strcpy ( string dst , string src )
FIXME : check for null pointers first ?
= = = = = = = = = = = = = = = = =
*/
2004-09-13 02:22:02 +00:00
void PF_MVDSV_strcpy ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
char * src = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
char * dest = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
int * ident ;
ident = ( int * ) ( dest - 8 ) ;
if ( * ident ! = PRSTR )
{
Con_Printf ( " PF_strcpy: not an allocated string \n " ) ;
return ;
}
if ( ident [ 0 ] < strlen ( src ) + 1 )
{
Con_Printf ( " PF_strcpy: allocated string is not big enough. \n " ) ;
return ;
}
strcpy ( dest , src ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_strncpy
void strcpy ( string dst , string src , float count )
FIXME : check for null pointers first ?
= = = = = = = = = = = = = = = = =
*/
2004-09-13 02:22:02 +00:00
void PF_MVDSV_strncpy ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
strncpy ( PR_GetStringOfs ( prinst , OFS_PARM0 ) , PR_GetStringOfs ( prinst , OFS_PARM1 ) , ( int ) G_FLOAT ( OFS_PARM2 ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
PF_strstr
string strstr ( string str , string sub )
= = = = = = = = = = = = = = = = =
*/
void PF_strstr ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * str , * sub , * p ;
str = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
sub = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
if ( ( p = strstr ( str , sub ) ) = = NULL )
{
G_INT ( OFS_RETURN ) = 0 ;
return ;
}
RETURN_TSTRING ( p ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
SV_CleanName_Init
sets chararcter table to translate quake texts to more friendly texts
= = = = = = = = = = = = = = = = = = = =
*/
char chartbl2 [ 256 ] ;
void PR_CleanLogText_Init ( void )
{
int i ;
for ( i = 0 ; i < 256 ; i + + )
chartbl2 [ i ] = ( i & 127 ) < 32 ? ' ' : i & 127 ;
chartbl2 [ 13 ] = 13 ;
chartbl2 [ 10 ] = 10 ;
// special cases
// numbers
for ( i = 18 ; i < 28 ; i + + )
chartbl2 [ i ] = chartbl2 [ i + 128 ] = i + 30 ;
// brackets
chartbl2 [ 29 ] = chartbl2 [ 29 + 128 ] = chartbl2 [ 128 ] = ' ( ' ;
chartbl2 [ 31 ] = chartbl2 [ 31 + 128 ] = chartbl2 [ 130 ] = ' ) ' ;
chartbl2 [ 16 ] = chartbl2 [ 16 + 128 ] = ' [ ' ;
chartbl2 [ 17 ] = chartbl2 [ 17 + 128 ] = ' ] ' ;
// hash
for ( i = 1 ; i < 10 ; i + + ) // 5 redefined as '.'
chartbl2 [ i ] = chartbl2 [ i + 128 ] = ' # ' ;
chartbl2 [ 11 ] = chartbl2 [ 11 + 128 ] = ' # ' ;
// dot
chartbl2 [ 5 ] = chartbl2 [ 14 ] = chartbl2 [ 15 ] = chartbl2 [ 28 ] = chartbl2 [ 46 ] = ' . ' ;
chartbl2 [ 5 + 128 ] = chartbl2 [ 14 + 128 ] = chartbl2 [ 15 + 128 ] = chartbl2 [ 28 + 128 ] = chartbl2 [ 46 + 128 ] = ' . ' ;
// left arrow
chartbl2 [ 127 ] = ' > ' ;
// right arrow
chartbl2 [ 141 ] = ' < ' ;
// '='
chartbl2 [ 30 ] = chartbl2 [ 129 ] = chartbl2 [ 30 + 128 ] = ' = ' ;
// whitespaces
chartbl2 [ 12 ] = chartbl2 [ 12 + 128 ] = chartbl2 [ 138 ] = ' ' ;
chartbl2 [ 33 ] = chartbl2 [ 33 + 128 ] = ' ! ' ;
}
void PR_CleanText ( unsigned char * text )
{
for ( ; * text ; text + + )
* text = chartbl2 [ * text ] ;
}
/*
= = = = = = = = = = = = = = = =
PF_log
void log ( string name , float console , string text )
= = = = = = = = = = = = = = = = =
*/
void PF_log ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char name [ MAX_OSPATH ] , * text ;
FILE * file ;
_snprintf ( name , MAX_OSPATH , " %s/%s.log " , com_gamedir , PR_GetStringOfs ( prinst , OFS_PARM0 ) ) ;
text = PF_VarString ( prinst , 2 , pr_globals ) ;
PR_CleanText ( text ) ;
if ( ( file = fopen ( name , " a " ) ) = = NULL )
{
Sys_Printf ( " coldn't open log file %s \n " , name ) ;
}
else
{
fprintf ( file , text ) ;
fflush ( file ) ;
fclose ( file ) ;
}
if ( G_FLOAT ( OFS_PARM1 ) )
Con_Printf ( " %s " , text ) ;
}
# ifdef Q2BSPS
void PF_OpenPortal ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
if ( sv . worldmodel - > fromgame = = fg_quake2 )
{
int i , portal = G_FLOAT ( OFS_PARM0 ) ;
int state = G_FLOAT ( OFS_PARM1 ) ! = 0 ;
client_t * client ;
for ( client = svs . clients , i = 0 ; i < sv . allocated_client_slots ; i + + , client + + )
{
if ( client - > state > = cs_connected )
{
ClientReliableWrite_Begin ( client , svc_setportalstate , 3 ) ;
if ( state )
ClientReliableWrite_Short ( client , portal | ( state < < 15 ) ) ;
else
ClientReliableWrite_Short ( client , portal ) ;
}
}
CMQ2_SetAreaPortalState ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
}
}
# endif
//EXTENSION: DP_QC_COPYENTITY
//void(entity from, entity to) copyentity = #400
//copies data from one entity to another
2004-11-21 07:31:26 +00:00
static void PF_copyentity ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
2004-08-23 00:15:46 +00:00
{
edict_t * in , * out ;
in = G_EDICT ( prinst , OFS_PARM0 ) ;
out = G_EDICT ( prinst , OFS_PARM1 ) ;
2005-03-28 07:05:38 +00:00
memcpy ( out - > v , in - > v , pr_edict_size ) ;
2004-12-19 04:37:42 +00:00
SV_LinkEdict ( out , false ) ;
2004-08-23 00:15:46 +00:00
}
//EXTENSION: DP_QC_ETOS
//string(entity ent) etos = #65
void PF_etos ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
2005-05-20 03:32:53 +00:00
s = PF_TempStr ( prinst ) ;
2004-08-23 00:15:46 +00:00
sprintf ( s , " entity %i " , G_EDICTNUM ( prinst , OFS_PARM0 ) ) ;
G_INT ( OFS_RETURN ) = ( int ) PR_SetString ( prinst , s ) ;
}
2004-10-13 06:37:44 +00:00
2004-08-23 00:15:46 +00:00
//EXTENSION: DP_QC_FINDCHAIN
//entity(string field, string match) findchain = #402
//chained search for strings in entity fields
void PF_findchain ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i , f ;
char * s , * t ;
edict_t * ent , * chain ;
2004-11-23 00:35:37 +00:00
chain = ( edict_t * ) * prinst - > parms - > sv_edicts ;
2004-08-23 00:15:46 +00:00
f = G_INT ( OFS_PARM0 ) + prinst - > fieldadjust ;
s = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
2004-11-23 00:35:37 +00:00
for ( i = 1 ; i < * prinst - > parms - > sv_num_edicts ; i + + )
2004-08-23 00:15:46 +00:00
{
2004-11-23 00:35:37 +00:00
ent = EDICT_NUM ( prinst , i ) ;
2004-08-23 00:15:46 +00:00
if ( ent - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
t = * ( string_t * ) & ( ( float * ) ent - > v ) [ f ] + prinst - > stringtable ;
2004-08-23 00:15:46 +00:00
if ( ! t )
continue ;
if ( strcmp ( t , s ) )
continue ;
2005-03-28 00:11:59 +00:00
ent - > v - > chain = EDICT_TO_PROG ( prinst , chain ) ;
2004-08-23 00:15:46 +00:00
chain = ent ;
}
RETURN_EDICT ( prinst , chain ) ;
}
//EXTENSION: DP_QC_FINDCHAINFLOAT
//entity(string field, float match) findchainfloat = #403
//chained search for float, int, and entity reference fields
void PF_findchainfloat ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i , f ;
float s ;
edict_t * ent , * chain ;
2004-11-23 00:35:37 +00:00
chain = ( edict_t * ) * prinst - > parms - > sv_edicts ;
2004-08-23 00:15:46 +00:00
f = G_INT ( OFS_PARM0 ) + prinst - > fieldadjust ;
s = G_FLOAT ( OFS_PARM1 ) ;
2004-11-23 00:35:37 +00:00
for ( i = 1 ; i < * prinst - > parms - > sv_num_edicts ; i + + )
2004-08-23 00:15:46 +00:00
{
2004-11-23 00:35:37 +00:00
ent = EDICT_NUM ( prinst , i ) ;
2004-08-23 00:15:46 +00:00
if ( ent - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ( ( float * ) ent - > v ) [ f ] ! = s )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
ent - > v - > chain = EDICT_TO_PROG ( prinst , chain ) ;
2004-08-23 00:15:46 +00:00
chain = ent ;
}
RETURN_EDICT ( prinst , chain ) ;
}
2004-10-13 06:37:44 +00:00
//EXTENSION: DP_QC_FINDCHAINFLAGS
//entity(string field, float match) findchainflags = #450
//chained search for float, int, and entity reference fields
void PF_findchainflags ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i , f ;
int s ;
edict_t * ent , * chain ;
2004-11-23 00:35:37 +00:00
chain = ( edict_t * ) * prinst - > parms - > sv_edicts ;
2004-10-13 06:37:44 +00:00
f = G_INT ( OFS_PARM0 ) + prinst - > fieldadjust ;
s = G_FLOAT ( OFS_PARM1 ) ;
2004-11-23 00:35:37 +00:00
for ( i = 1 ; i < * prinst - > parms - > sv_num_edicts ; i + + )
2004-10-13 06:37:44 +00:00
{
2004-11-23 00:35:37 +00:00
ent = EDICT_NUM ( prinst , i ) ;
2004-10-13 06:37:44 +00:00
if ( ent - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ! ( ( int ) ( ( float * ) ent - > v ) [ f ] & s ) )
2004-10-13 06:37:44 +00:00
continue ;
2005-03-28 00:11:59 +00:00
ent - > v - > chain = EDICT_TO_PROG ( prinst , chain ) ;
2004-10-13 06:37:44 +00:00
chain = ent ;
}
RETURN_EDICT ( prinst , chain ) ;
}
2004-08-23 00:15:46 +00:00
//EXTENSION: DP_QC_FINDFLOAT
//entity(entity start, float fld, float match) findfloat = #98
void PF_FindFloat ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int e , f ;
2004-11-23 00:35:37 +00:00
int s ;
2004-08-23 00:15:46 +00:00
edict_t * ed ;
2004-11-17 17:52:18 +00:00
if ( * prinst - > callargc ! = 3 ) //I can hate mvdsv if I want to.
{
PR_BIError ( prinst , " PF_FindFloat (#98): callargc != 3 \n Did you mean to set pr_imitatemvdsv to 1? " ) ;
return ;
}
2004-08-23 00:15:46 +00:00
e = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
f = G_INT ( OFS_PARM1 ) + prinst - > fieldadjust ;
2004-11-23 00:35:37 +00:00
s = G_INT ( OFS_PARM2 ) ;
2004-08-23 00:15:46 +00:00
2004-11-21 07:31:26 +00:00
for ( e + + ; e < * prinst - > parms - > sv_num_edicts ; e + + )
2004-08-23 00:15:46 +00:00
{
ed = EDICT_NUM ( prinst , e ) ;
if ( ed - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ( ( int * ) ed - > v ) [ f ] = = s )
2004-08-23 00:15:46 +00:00
{
RETURN_EDICT ( prinst , ed ) ;
return ;
}
}
2004-11-21 07:31:26 +00:00
RETURN_EDICT ( prinst , * prinst - > parms - > sv_edicts ) ;
2004-08-23 00:15:46 +00:00
}
2004-10-13 06:37:44 +00:00
//EXTENSION: DP_QC_FINDFLAGS
//entity(entity start, float fld, float match) findflags = #449
void PF_FindFlags ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int e , f ;
int s ;
edict_t * ed ;
e = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
f = G_INT ( OFS_PARM1 ) + prinst - > fieldadjust ;
s = G_FLOAT ( OFS_PARM2 ) ;
2004-11-23 00:35:37 +00:00
for ( e + + ; e < * prinst - > parms - > sv_num_edicts ; e + + )
2004-10-13 06:37:44 +00:00
{
ed = EDICT_NUM ( prinst , e ) ;
if ( ed - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ( ( float * ) ed - > v ) [ f ] & s )
2004-10-13 06:37:44 +00:00
{
RETURN_EDICT ( prinst , ed ) ;
return ;
}
}
2004-11-23 00:35:37 +00:00
RETURN_EDICT ( prinst , * prinst - > parms - > sv_edicts ) ;
2004-10-13 06:37:44 +00:00
}
2004-08-23 00:15:46 +00:00
//EXTENSION: DP_QC_RANDOMVEC
//vector() randomvec = #91
void PF_randomvec ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
vec3_t temp ;
do
{
temp [ 0 ] = ( rand ( ) & 32767 ) * ( 2.0 / 32767.0 ) - 1.0 ;
temp [ 1 ] = ( rand ( ) & 32767 ) * ( 2.0 / 32767.0 ) - 1.0 ;
temp [ 2 ] = ( rand ( ) & 32767 ) * ( 2.0 / 32767.0 ) - 1.0 ;
} while ( DotProduct ( temp , temp ) > = 1 ) ;
VectorCopy ( temp , G_VECTOR ( OFS_RETURN ) ) ;
}
//EXTENSION: DP_QC_VECTORVECTORS
//void(vector dir) vectorvectors = #432
//Writes new values for v_forward, v_up, and v_right based on the given forward vector
void PF_vectorvectors ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
VectorCopy ( G_VECTOR ( OFS_PARM0 ) , P_VEC ( v_forward ) ) ;
VectorNormalize ( P_VEC ( v_forward ) ) ;
VectorVectors ( P_VEC ( v_forward ) , P_VEC ( v_right ) , P_VEC ( v_up ) ) ;
}
//EXTENSION: DP_QC_MINMAXBOUND
//float(float a, floats) min = #94
void PF_min ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
float f ;
if ( * prinst - > callargc = = 2 )
{
G_FLOAT ( OFS_RETURN ) = min ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
}
else if ( * prinst - > callargc > = 3 )
{
f = G_FLOAT ( OFS_PARM0 ) ;
for ( i = 1 ; i < * prinst - > callargc ; i + + )
{
if ( G_FLOAT ( ( OFS_PARM0 + i * 3 ) ) < f )
f = G_FLOAT ( ( OFS_PARM0 + i * 3 ) ) ;
}
G_FLOAT ( OFS_RETURN ) = f ;
}
else
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_min: must supply at least 2 floats \n " ) ;
2004-08-23 00:15:46 +00:00
}
//float(float a, floats) max = #95
void PF_max ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int i ;
float f ;
if ( * prinst - > callargc = = 2 )
{
G_FLOAT ( OFS_RETURN ) = max ( G_FLOAT ( OFS_PARM0 ) , G_FLOAT ( OFS_PARM1 ) ) ;
}
else if ( * prinst - > callargc > = 3 )
{
f = G_FLOAT ( OFS_PARM0 ) ;
for ( i = 1 ; i < * prinst - > callargc ; i + + ) {
if ( G_FLOAT ( ( OFS_PARM0 + i * 3 ) ) > f )
f = G_FLOAT ( ( OFS_PARM0 + i * 3 ) ) ;
}
G_FLOAT ( OFS_RETURN ) = f ;
}
else
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_min: must supply at least 2 floats \n " ) ;
2004-08-23 00:15:46 +00:00
}
}
//float(float minimum, float val, float maximum) bound = #96
void PF_bound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
if ( G_FLOAT ( OFS_PARM1 ) > G_FLOAT ( OFS_PARM2 ) )
G_FLOAT ( OFS_RETURN ) = G_FLOAT ( OFS_PARM2 ) ;
else if ( G_FLOAT ( OFS_PARM1 ) < G_FLOAT ( OFS_PARM0 ) )
G_FLOAT ( OFS_RETURN ) = G_FLOAT ( OFS_PARM0 ) ;
else
G_FLOAT ( OFS_RETURN ) = G_FLOAT ( OFS_PARM1 ) ;
}
//EXTENSION: KRIMZON_SV_PARSECLIENTCOMMAND
//void(entity e, string s) clientcommand = #440
//executes a command string as if it came from the specified client
void PF_clientcommand ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
client_t * temp_client ;
int i ;
//find client for this entity
i = NUM_FOR_EDICT ( prinst , G_EDICT ( prinst , OFS_PARM0 ) ) - 1 ;
if ( i < 0 | | i > = sv . allocated_client_slots )
2004-11-21 07:31:26 +00:00
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_clientcommand: entity is not a client " ) ;
2004-11-21 07:31:26 +00:00
return ;
}
2004-08-23 00:15:46 +00:00
temp_client = host_client ;
host_client = & svs . clients [ i ] ;
if ( host_client - > state = = cs_connected | | host_client - > state = = cs_spawned )
2004-12-22 08:04:06 +00:00
{
SV_ExecuteUserCommand ( PF_VarString ( prinst , 1 , pr_globals ) , true ) ;
}
else
Con_Printf ( " PF_clientcommand: client is not active \n " ) ;
2004-08-23 00:15:46 +00:00
host_client = temp_client ;
if ( host_client )
sv_player = host_client - > edict ;
}
void PF_AdvanceFrame ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * Ent ;
float Start , End , Result ;
Ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
Start = G_FLOAT ( OFS_PARM0 ) ;
End = G_FLOAT ( OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
if ( ( Start < End & & ( Ent - > v - > frame < Start | | Ent - > v - > frame > End ) ) | |
( Start > End & & ( Ent - > v - > frame > Start | | Ent - > v - > frame < End ) ) )
2004-08-23 00:15:46 +00:00
{ // Didn't start in the range
2005-03-28 00:11:59 +00:00
Ent - > v - > frame = Start ;
2004-08-23 00:15:46 +00:00
Result = 0 ;
}
2005-03-28 00:11:59 +00:00
else if ( Ent - > v - > frame = = End )
2004-08-23 00:15:46 +00:00
{ // Wrapping
2005-03-28 00:11:59 +00:00
Ent - > v - > frame = Start ;
2004-08-23 00:15:46 +00:00
Result = 1 ;
}
else if ( End > Start )
{ // Regular Advance
2005-03-28 00:11:59 +00:00
Ent - > v - > frame + + ;
if ( Ent - > v - > frame = = End )
2004-08-23 00:15:46 +00:00
Result = 2 ;
else
Result = 0 ;
}
else if ( End < Start )
{ // Reverse Advance
2005-03-28 00:11:59 +00:00
Ent - > v - > frame - - ;
if ( Ent - > v - > frame = = End )
2004-08-23 00:15:46 +00:00
Result = 2 ;
else
Result = 0 ;
}
else
{
2005-03-28 00:11:59 +00:00
Ent - > v - > frame = End ;
2004-08-23 00:15:46 +00:00
Result = 1 ;
}
G_FLOAT ( OFS_RETURN ) = Result ;
}
void PF_RewindFrame ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * Ent ;
float Start , End , Result ;
Ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
Start = G_FLOAT ( OFS_PARM0 ) ;
End = G_FLOAT ( OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
if ( Ent - > v - > frame > Start | | Ent - > v - > frame < End )
2004-08-23 00:15:46 +00:00
{ // Didn't start in the range
2005-03-28 00:11:59 +00:00
Ent - > v - > frame = Start ;
2004-08-23 00:15:46 +00:00
Result = 0 ;
}
2005-03-28 00:11:59 +00:00
else if ( Ent - > v - > frame = = End )
2004-08-23 00:15:46 +00:00
{ // Wrapping
2005-03-28 00:11:59 +00:00
Ent - > v - > frame = Start ;
2004-08-23 00:15:46 +00:00
Result = 1 ;
}
else
{ // Regular Advance
2005-03-28 00:11:59 +00:00
Ent - > v - > frame - - ;
if ( Ent - > v - > frame = = End ) Result = 2 ;
2004-08-23 00:15:46 +00:00
else Result = 0 ;
}
G_FLOAT ( OFS_RETURN ) = Result ;
}
# define WF_NORMAL_ADVANCE 0
# define WF_CYCLE_STARTED 1
# define WF_CYCLE_WRAPPED 2
# define WF_LAST_FRAME 3
void PF_advanceweaponframe ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * ent ;
float startframe , endframe ;
float state ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
startframe = G_FLOAT ( OFS_PARM0 ) ;
endframe = G_FLOAT ( OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
if ( ( endframe > startframe & & ( ent - > v - > weaponframe > endframe | | ent - > v - > weaponframe < startframe ) ) | |
( endframe < startframe & & ( ent - > v - > weaponframe < endframe | | ent - > v - > weaponframe > startframe ) ) )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
ent - > v - > weaponframe = startframe ;
2004-08-23 00:15:46 +00:00
state = WF_CYCLE_STARTED ;
}
2005-03-28 00:11:59 +00:00
else if ( ent - > v - > weaponframe = = endframe )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
ent - > v - > weaponframe = startframe ;
2004-08-23 00:15:46 +00:00
state = WF_CYCLE_WRAPPED ;
}
else
{
if ( startframe > endframe )
2005-03-28 00:11:59 +00:00
ent - > v - > weaponframe = ent - > v - > weaponframe - 1 ;
2004-08-23 00:15:46 +00:00
else if ( startframe < endframe )
2005-03-28 00:11:59 +00:00
ent - > v - > weaponframe = ent - > v - > weaponframe + 1 ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ent - > v - > weaponframe = = endframe )
2004-08-23 00:15:46 +00:00
state = WF_LAST_FRAME ;
else
state = WF_NORMAL_ADVANCE ;
}
G_FLOAT ( OFS_RETURN ) = state ;
}
void PF_setclass ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float NewClass ;
int entnum ;
edict_t * e ;
client_t * client ;
// client_t *old;
char temp [ 1024 ] ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
NewClass = G_FLOAT ( OFS_PARM1 ) ;
if ( entnum < 1 | | entnum > sv . allocated_client_slots )
{
Con_Printf ( " tried to change class of a non-client \n " ) ;
return ;
}
client = & svs . clients [ entnum - 1 ] ;
2005-03-28 00:11:59 +00:00
e - > v - > playerclass = NewClass ;
2004-08-23 00:15:46 +00:00
client - > playerclass = NewClass ;
sprintf ( temp , " %d " , ( int ) NewClass ) ;
2005-03-07 08:55:30 +00:00
Info_SetValueForKey ( client - > userinfo , " playerclass " , temp , sizeof ( client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
client - > sendinfo = true ;
}
void PF_v_factor ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
// returns (v_right * factor_x) + (v_forward * factor_y) + (v_up * factor_z)
{
float * range ;
vec3_t result ;
range = G_VECTOR ( OFS_PARM0 ) ;
result [ 0 ] = ( P_VEC ( v_right ) [ 0 ] * range [ 0 ] ) +
( P_VEC ( v_forward ) [ 0 ] * range [ 1 ] ) +
( P_VEC ( v_up ) [ 0 ] * range [ 2 ] ) ;
result [ 1 ] = ( P_VEC ( v_right ) [ 1 ] * range [ 0 ] ) +
( P_VEC ( v_forward ) [ 1 ] * range [ 1 ] ) +
( P_VEC ( v_up ) [ 1 ] * range [ 2 ] ) ;
result [ 2 ] = ( P_VEC ( v_right ) [ 2 ] * range [ 0 ] ) +
( P_VEC ( v_forward ) [ 2 ] * range [ 1 ] ) +
( P_VEC ( v_up ) [ 2 ] * range [ 2 ] ) ;
VectorCopy ( result , G_VECTOR ( OFS_RETURN ) ) ;
}
void PF_v_factorrange ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
// returns (v_right * factor_x) + (v_forward * factor_y) + (v_up * factor_z)
{
float num , * minv , * maxv ;
vec3_t result , r2 ;
minv = G_VECTOR ( OFS_PARM0 ) ;
maxv = G_VECTOR ( OFS_PARM1 ) ;
num = ( rand ( ) & 0x7fff ) / ( ( float ) 0x7fff ) ;
result [ 0 ] = ( ( maxv [ 0 ] - minv [ 0 ] ) * num ) + minv [ 0 ] ;
num = ( rand ( ) & 0x7fff ) / ( ( float ) 0x7fff ) ;
result [ 1 ] = ( ( maxv [ 1 ] - minv [ 1 ] ) * num ) + minv [ 1 ] ;
num = ( rand ( ) & 0x7fff ) / ( ( float ) 0x7fff ) ;
result [ 2 ] = ( ( maxv [ 2 ] - minv [ 2 ] ) * num ) + minv [ 2 ] ;
r2 [ 0 ] = ( P_VEC ( v_right ) [ 0 ] * result [ 0 ] ) +
( P_VEC ( v_forward ) [ 0 ] * result [ 1 ] ) +
( P_VEC ( v_up ) [ 0 ] * result [ 2 ] ) ;
r2 [ 1 ] = ( P_VEC ( v_right ) [ 1 ] * result [ 0 ] ) +
( P_VEC ( v_forward ) [ 1 ] * result [ 1 ] ) +
( P_VEC ( v_up ) [ 1 ] * result [ 2 ] ) ;
r2 [ 2 ] = ( P_VEC ( v_right ) [ 2 ] * result [ 0 ] ) +
( P_VEC ( v_forward ) [ 2 ] * result [ 1 ] ) +
( P_VEC ( v_up ) [ 2 ] * result [ 2 ] ) ;
VectorCopy ( r2 , G_VECTOR ( OFS_RETURN ) ) ;
}
char * T_GetString ( int num ) ;
void PF_plaque_draw ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s ;
if ( sv . demofile )
return ;
if ( G_FLOAT ( OFS_PARM1 ) = = 0 )
s = " " ;
else
s = T_GetString ( G_FLOAT ( OFS_PARM1 ) - 1 ) ;
pr_netprogfuncs = prinst ;
pr_netglob = pr_globals ;
if ( G_FLOAT ( OFS_PARM0 ) = = MSG_ONE )
{
client_t * cl = Write_GetClient ( ) ;
if ( ! cl )
return ;
2004-11-17 17:52:18 +00:00
ClientReliableWrite_Begin ( cl , svc_centerprint , 4 + strlen ( s ) ) ;
if ( * s )
{
ClientReliableWrite_Byte ( cl , ' / ' ) ;
ClientReliableWrite_Byte ( cl , ' P ' ) ;
}
2004-08-23 00:15:46 +00:00
ClientReliableWrite_String ( cl , s ) ;
}
else
{
MSG_WriteByte ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , svc_centerprint ) ;
2004-11-17 17:52:18 +00:00
if ( * s )
{
MSG_WriteByte ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , ' / ' ) ;
MSG_WriteByte ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , ' P ' ) ;
}
2004-08-23 00:15:46 +00:00
MSG_WriteString ( WriteDest ( G_FLOAT ( OFS_PARM0 ) ) , s ) ;
}
}
void PF_movestep ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
vec3_t v ;
edict_t * ent ;
int oldself ;
qboolean set_trace ;
ent = PROG_TO_EDICT ( prinst , pr_global_struct - > self ) ;
v [ 0 ] = G_FLOAT ( OFS_PARM0 ) ;
v [ 1 ] = G_FLOAT ( OFS_PARM1 ) ;
v [ 2 ] = G_FLOAT ( OFS_PARM2 ) ;
set_trace = G_FLOAT ( OFS_PARM3 ) ;
// save program state, because SV_movestep may call other progs
oldself = pr_global_struct - > self ;
G_INT ( OFS_RETURN ) = SV_movestep ( ent , v , false , true , set_trace ? pr_globals : NULL ) ;
// restore program state
pr_global_struct - > self = oldself ;
}
void PF_concatv ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * in , * range ;
vec3_t result ;
in = G_VECTOR ( OFS_PARM0 ) ;
range = G_VECTOR ( OFS_PARM1 ) ;
VectorCopy ( in , result ) ;
if ( result [ 0 ] < - range [ 0 ] ) result [ 0 ] = - range [ 0 ] ;
if ( result [ 0 ] > range [ 0 ] ) result [ 0 ] = range [ 0 ] ;
if ( result [ 1 ] < - range [ 1 ] ) result [ 1 ] = - range [ 1 ] ;
if ( result [ 1 ] > range [ 1 ] ) result [ 1 ] = range [ 1 ] ;
if ( result [ 2 ] < - range [ 2 ] ) result [ 2 ] = - range [ 2 ] ;
if ( result [ 2 ] > range [ 2 ] ) result [ 2 ] = range [ 2 ] ;
VectorCopy ( result , G_VECTOR ( OFS_RETURN ) ) ;
}
void PF_matchAngleToSlope ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * actor ;
vec3_t v_forward , old_forward , old_right , new_angles2 = { 0 , 0 , 0 } ;
float pitch , mod , dot ;
// OFS_PARM0 is used by PF_vectoangles below
actor = G_EDICT ( prinst , OFS_PARM1 ) ;
2005-03-28 00:11:59 +00:00
AngleVectors ( actor - > v - > angles , old_forward , old_right , P_VEC ( v_up ) ) ;
2004-08-23 00:15:46 +00:00
PF_vectoangles ( prinst , pr_globals ) ;
pitch = G_FLOAT ( OFS_RETURN ) - 90 ;
new_angles2 [ 1 ] = G_FLOAT ( OFS_RETURN + 1 ) ;
AngleVectors ( new_angles2 , v_forward , P_VEC ( v_right ) , P_VEC ( v_up ) ) ;
mod = DotProduct ( v_forward , old_right ) ;
if ( mod < 0 )
mod = 1 ;
else
mod = - 1 ;
dot = DotProduct ( v_forward , old_forward ) ;
2005-03-28 00:11:59 +00:00
actor - > v - > angles [ 0 ] = dot * pitch ;
actor - > v - > angles [ 2 ] = ( 1 - fabs ( dot ) ) * pitch * mod ;
2004-08-23 00:15:46 +00:00
}
void PF_starteffect ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
Con_DPrintf ( " Start effect %i \n " , ( int ) G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_endeffect ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
Con_DPrintf ( " Stop effect %i \n " , ( int ) G_FLOAT ( OFS_PARM0 ) ) ;
}
void PF_rain_go ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
}
void PF_StopSound ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
}
void PF_getstring ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * s = T_GetString ( G_FLOAT ( OFS_PARM0 ) - 1 ) ;
RETURN_PSTRING ( s ) ;
}
void PF_RegisterTEnt ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int arg ;
int i ;
int nettype = G_FLOAT ( OFS_PARM0 ) ;
char * effectname = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
if ( sv . state ! = ss_loading )
{
2004-11-17 17:52:18 +00:00
PR_BIError ( prinst , " PF_RegisterTEnt: Registration can only be done in spawn functions " ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
for ( i = 0 ; i < 255 ; i + + )
{
if ( ! * sv . customtents [ i ] . particleeffecttype )
break ;
if ( ! strcmp ( effectname , sv . customtents [ i ] . particleeffecttype ) )
break ;
}
if ( i = = 255 )
{
Con_Printf ( " Too many custom effects \n " ) ;
G_FLOAT ( OFS_RETURN ) = - 1 ;
return ;
}
Q_strncpyz ( sv . customtents [ i ] . particleeffecttype , effectname , sizeof ( sv . customtents [ i ] . particleeffecttype ) ) ;
sv . customtents [ i ] . netstyle = nettype ;
arg = 2 ;
if ( nettype & CTE_STAINS )
{
VectorCopy ( G_VECTOR ( OFS_PARM0 + arg * 3 ) , sv . customtents [ i ] . stain ) ;
sv . customtents [ i ] . radius = G_FLOAT ( OFS_PARM1 + arg * 3 ) ;
arg + = 2 ;
}
if ( nettype & CTE_GLOWS )
{
sv . customtents [ i ] . dlightrgb [ 0 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 0 ) * 255 ;
sv . customtents [ i ] . dlightrgb [ 1 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 1 ) * 255 ;
sv . customtents [ i ] . dlightrgb [ 2 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 2 ) * 255 ;
sv . customtents [ i ] . dlightradius = G_FLOAT ( OFS_PARM1 + arg * 3 ) / 4 ;
sv . customtents [ i ] . dlighttime = G_FLOAT ( OFS_PARM2 + arg * 3 ) * 16 ;
arg + = 3 ;
2004-08-30 06:07:13 +00:00
if ( nettype & CTE_CHANNELFADE )
{
sv . customtents [ i ] . dlightcfade [ 0 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 0 ) * 64 ;
sv . customtents [ i ] . dlightcfade [ 1 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 1 ) * 64 ;
sv . customtents [ i ] . dlightcfade [ 2 ] = G_FLOAT ( OFS_PARM0 + arg * 3 + 2 ) * 64 ;
arg + + ; // we're out now..
}
2004-08-23 00:15:46 +00:00
}
if ( arg ! = * prinst - > callargc )
Con_Printf ( " Bad argument count \n " ) ;
G_FLOAT ( OFS_RETURN ) = i ;
}
void PF_CustomTEnt ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int type ;
int arg ;
float * org = G_VECTOR ( OFS_PARM1 ) ;
if ( sv . multicast . cursize )
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , 0 , PEXT_CUSTOMTEMPEFFECTS ) ; //do a multicast with the current buffer to all players who won't get the new effect.
2004-08-23 00:15:46 +00:00
type = G_FLOAT ( OFS_PARM0 ) ;
if ( type < 0 | | type > = 255 )
return ;
MSG_WriteByte ( & sv . multicast , svc_customtempent ) ;
MSG_WriteByte ( & sv . multicast , type ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
type = sv . customtents [ type ] . netstyle ;
arg = 2 ;
2005-01-28 19:26:24 +00:00
if ( type & CTE_ISBEAM )
2004-08-23 00:15:46 +00:00
{
2005-01-28 19:26:24 +00:00
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 + arg * 3 ) [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 + arg * 3 ) [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 + arg * 3 ) [ 2 ] ) ;
2004-08-23 00:15:46 +00:00
arg + + ;
}
2005-01-28 19:26:24 +00:00
else
2004-08-23 00:15:46 +00:00
{
2005-01-28 19:26:24 +00:00
if ( type & CTE_CUSTOMCOUNT )
{
MSG_WriteByte ( & sv . multicast , G_FLOAT ( OFS_PARM0 + arg * 3 ) ) ;
arg + + ;
}
if ( type & CTE_CUSTOMDIRECTION )
{
MSG_WriteDir ( & sv . multicast , G_VECTOR ( OFS_PARM0 + arg * 3 ) ) ;
arg + + ;
}
2004-08-23 00:15:46 +00:00
}
if ( arg ! = * prinst - > callargc )
Con_Printf ( " PF_CusromTEnt: bad number of arguments for particle type \n " ) ;
2004-08-31 23:58:18 +00:00
SV_MulticastProtExt ( org , MULTICAST_PVS , pr_global_struct - > dimension_send , PEXT_CUSTOMTEMPEFFECTS , 0 ) ; //now send the new multicast to all that will.
2004-08-23 00:15:46 +00:00
}
void PF_Abort ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
svprogfuncs - > AbortStack ( svprogfuncs ) ;
}
typedef struct qcstate_s {
float resumetime ;
struct qcthread_s * thread ;
int self ;
int other ;
struct qcstate_s * next ;
} qcstate_t ;
qcstate_t * qcthreads ;
void PR_RunThreads ( void )
{
struct globalvars_s * pr_globals ;
qcstate_t * state = qcthreads , * next ;
qcthreads = NULL ;
while ( state )
{
next = state - > next ;
if ( state - > resumetime > sv . time )
{ //not time yet, reform origional list.
state - > next = qcthreads ;
qcthreads = state ;
}
else
{ //call it and forget it ever happened. The Sleep biltin will recreate if needed.
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , EDICT_NUM ( svprogfuncs , state - > self ) ) ;
pr_global_struct - > other = EDICT_TO_PROG ( svprogfuncs , EDICT_NUM ( svprogfuncs , state - > other ) ) ;
G_FLOAT ( OFS_RETURN ) = 1 ;
svprogfuncs - > RunThread ( svprogfuncs , state - > thread ) ;
svprogfuncs - > parms - > memfree ( state - > thread ) ;
svprogfuncs - > parms - > memfree ( state ) ;
}
state = next ;
}
}
void PR_ClearThreads ( void )
{
qcstate_t * state = qcthreads , * next ;
qcthreads = NULL ;
while ( state )
{
next = state - > next ;
svprogfuncs - > parms - > memfree ( state - > thread ) ;
svprogfuncs - > parms - > memfree ( state ) ;
state = next ;
}
}
void PF_Sleep ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
qcstate_t * state ;
struct qcthread_s * thread ;
float sleeptime ;
sleeptime = G_FLOAT ( OFS_PARM0 ) ;
thread = svprogfuncs - > Fork ( svprogfuncs ) ;
state = svprogfuncs - > parms - > memalloc ( sizeof ( qcstate_t ) ) ;
state - > next = qcthreads ;
qcthreads = state ;
state - > resumetime = sv . time + sleeptime ;
state - > self = NUM_FOR_EDICT ( svprogfuncs , PROG_TO_EDICT ( svprogfuncs , pr_global_struct - > self ) ) ;
state - > other = NUM_FOR_EDICT ( svprogfuncs , PROG_TO_EDICT ( svprogfuncs , pr_global_struct - > other ) ) ;
state - > thread = thread ;
svprogfuncs - > AbortStack ( svprogfuncs ) ;
}
void PF_Fork ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
qcstate_t * state ;
struct qcthread_s * thread ;
thread = svprogfuncs - > Fork ( svprogfuncs ) ;
state = svprogfuncs - > parms - > memalloc ( sizeof ( qcstate_t ) ) ;
state - > next = qcthreads ;
qcthreads = state ;
state - > resumetime = sv . time ;
state - > self = NUM_FOR_EDICT ( svprogfuncs , PROG_TO_EDICT ( svprogfuncs , pr_global_struct - > self ) ) ;
state - > other = NUM_FOR_EDICT ( svprogfuncs , PROG_TO_EDICT ( svprogfuncs , pr_global_struct - > other ) ) ;
state - > thread = thread ;
PR_RunThreads ( ) ;
G_FLOAT ( OFS_RETURN ) = 0 ;
}
2004-08-31 23:58:18 +00:00
//QSG_DIMENSION_PLANES
//helper function
2004-09-04 17:52:32 +00:00
//float(float number, float quantity) bitshift = #218;
2004-08-31 23:58:18 +00:00
void PF_bitshift ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int bitmask ;
int shift ;
bitmask = G_FLOAT ( OFS_PARM0 ) ;
shift = G_FLOAT ( OFS_PARM1 ) ;
if ( shift < 0 )
bitmask > > = shift ;
else
bitmask < < = shift ;
G_FLOAT ( OFS_RETURN ) = bitmask ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_gunshot = #418;
void PF_te_gunshot ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
int count ;
if ( * svprogfuncs - > callargc > = 2 )
count = G_FLOAT ( OFS_PARM1 ) ;
else
count = 1 ;
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_GUNSHOT , count ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_spike = #419;
void PF_te_spike ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_SPIKE , 1 ) ;
}
void PF_te_lightningblood ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_LIGHTNINGBLOOD , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_superspike = #420;
void PF_te_superspike ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_SUPERSPIKE , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_explosion = #421;
void PF_te_explosion ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_EXPLOSION , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_tarexplosion = #422;
void PF_te_tarexplosion ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_TAREXPLOSION , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_wizspike = #423;
void PF_te_wizspike ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_WIZSPIKE , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_knightspike = #424;
void PF_te_knightspike ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_KNIGHTSPIKE , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_lavasplash = #425;
void PF_te_lavasplash ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_LAVASPLASH , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org) te_teleport = #426;
void PF_te_teleport ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_TELEPORT , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(vector org, float color) te_explosion2 = #427;
void PF_te_explosion2 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
//FIXME: QW doesn't support TE_EXPLOSION2...
SV_point_tempentity ( G_VECTOR ( OFS_PARM0 ) , TE_EXPLOSION , 1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(entity own, vector start, vector end) te_lightning1 = #428;
void PF_te_lightning1 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_beam_tempentity ( G_EDICTNUM ( prinst , OFS_PARM0 ) , G_VECTOR ( OFS_PARM1 ) , G_VECTOR ( OFS_PARM2 ) , TE_LIGHTNING1 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(entity own, vector start, vector end) te_lightning2 = #429;
void PF_te_lightning2 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_beam_tempentity ( G_EDICTNUM ( prinst , OFS_PARM0 ) , G_VECTOR ( OFS_PARM1 ) , G_VECTOR ( OFS_PARM2 ) , TE_LIGHTNING2 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(entity own, vector start, vector end) te_lightning3 = #430;
void PF_te_lightning3 ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_beam_tempentity ( G_EDICTNUM ( prinst , OFS_PARM0 ) , G_VECTOR ( OFS_PARM1 ) , G_VECTOR ( OFS_PARM2 ) , TE_LIGHTNING3 ) ;
}
//DP_TE_STANDARDEFFECTBUILTINS
//void(entity own, vector start, vector end) te_beam = #431;
void PF_te_beam ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
SV_beam_tempentity ( - 1 - G_EDICTNUM ( prinst , OFS_PARM0 ) , G_VECTOR ( OFS_PARM1 ) , G_VECTOR ( OFS_PARM2 ) , TE_LIGHTNING2 ) ;
}
2004-11-20 00:55:29 +00:00
//DP_TE_SPARK
void PF_te_spark ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-04-16 16:21:27 +00:00
float * org = G_VECTOR ( OFS_PARM0 ) ;
if ( G_FLOAT ( OFS_PARM2 ) < 1 )
return ;
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , DPTE_SPARK ) ;
// origin
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
// velocity
MSG_WriteByte ( & sv . multicast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 0 ] , 127 ) ) ;
MSG_WriteByte ( & sv . multicast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 1 ] , 127 ) ) ;
MSG_WriteByte ( & sv . multicast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 2 ] , 127 ) ) ;
// count
MSG_WriteByte ( & sv . multicast , bound ( 0 , ( int ) G_FLOAT ( OFS_PARM2 ) , 255 ) ) ;
//the nq version
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , DPTE_SPARK ) ;
// origin
MSG_WriteCoord ( & sv . nqmulticast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 2 ] ) ;
// velocity
MSG_WriteByte ( & sv . nqmulticast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 0 ] , 127 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 1 ] , 127 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , bound ( - 128 , ( int ) G_VECTOR ( OFS_PARM1 ) [ 2 ] , 127 ) ) ;
// count
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , ( int ) G_FLOAT ( OFS_PARM2 ) , 255 ) ) ;
# endif
SV_Multicast ( org , MULTICAST_PVS ) ;
2004-11-20 00:55:29 +00:00
}
// #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
void PF_te_smallflash ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-11-21 07:31:26 +00:00
float * org = G_VECTOR ( OFS_PARM0 ) ;
2005-04-16 16:21:27 +00:00
SV_point_tempentity ( org , DPTE_SMALLFLASH , 0 ) ;
2004-11-20 00:55:29 +00:00
}
// #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
void PF_te_customflash ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-04-16 16:21:27 +00:00
float * org = G_VECTOR ( OFS_PARM0 ) ;
if ( G_FLOAT ( OFS_PARM1 ) < 8 | | G_FLOAT ( OFS_PARM2 ) < ( 1.0 / 256.0 ) )
return ;
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , DPTE_CUSTOMFLASH ) ;
// origin
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 ) [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 ) [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , G_VECTOR ( OFS_PARM0 ) [ 2 ] ) ;
// radius
MSG_WriteByte ( & sv . multicast , bound ( 0 , G_FLOAT ( OFS_PARM1 ) / 8 - 1 , 255 ) ) ;
// lifetime
MSG_WriteByte ( & sv . multicast , bound ( 0 , G_FLOAT ( OFS_PARM2 ) / 256 - 1 , 255 ) ) ;
// color
MSG_WriteByte ( & sv . multicast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 0 ] * 255 , 255 ) ) ;
MSG_WriteByte ( & sv . multicast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 1 ] * 255 , 255 ) ) ;
MSG_WriteByte ( & sv . multicast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 2 ] * 255 , 255 ) ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , DPTE_CUSTOMFLASH ) ;
// origin
MSG_WriteCoord ( & sv . nqmulticast , G_VECTOR ( OFS_PARM0 ) [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , G_VECTOR ( OFS_PARM0 ) [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , G_VECTOR ( OFS_PARM0 ) [ 2 ] ) ;
// radius
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , G_FLOAT ( OFS_PARM1 ) / 8 - 1 , 255 ) ) ;
// lifetime
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , G_FLOAT ( OFS_PARM2 ) / 256 - 1 , 255 ) ) ;
// color
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 0 ] * 255 , 255 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 1 ] * 255 , 255 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , G_VECTOR ( OFS_PARM3 ) [ 2 ] * 255 , 255 ) ) ;
# endif
SV_Multicast ( org , MULTICAST_PVS ) ;
2004-11-20 00:55:29 +00:00
}
//#408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
void PF_te_particlecube ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-26 12:55:34 +00:00
float * min = G_VECTOR ( OFS_PARM0 ) ;
float * max = G_VECTOR ( OFS_PARM1 ) ;
float * dir = G_VECTOR ( OFS_PARM2 ) ;
float count = G_FLOAT ( OFS_PARM3 ) ;
float color = G_FLOAT ( OFS_PARM4 ) ;
float gravityflag = G_FLOAT ( OFS_PARM5 ) ;
float randomveljitter = G_FLOAT ( OFS_PARM6 ) ;
vec3_t org ;
if ( count < 1 )
return ;
// [vector] min [vector] max [vector] dir [short] count [byte] color [byte] gravity [coord] randomvel
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , DPTE_PARTICLECUBE ) ;
MSG_WriteCoord ( & sv . multicast , min [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , min [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , min [ 2 ] ) ;
MSG_WriteCoord ( & sv . multicast , max [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , max [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , max [ 2 ] ) ;
MSG_WriteCoord ( & sv . multicast , dir [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , dir [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , dir [ 2 ] ) ;
MSG_WriteShort ( & sv . multicast , bound ( 0 , count , 65535 ) ) ;
MSG_WriteByte ( & sv . multicast , bound ( 0 , color , 255 ) ) ;
MSG_WriteByte ( & sv . multicast , ( int ) gravityflag ! = 0 ) ;
MSG_WriteCoord ( & sv . multicast , randomveljitter ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , DPTE_PARTICLECUBE ) ;
MSG_WriteCoord ( & sv . nqmulticast , min [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , min [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , min [ 2 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , max [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , max [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , max [ 2 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , dir [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , dir [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , dir [ 2 ] ) ;
MSG_WriteShort ( & sv . nqmulticast , bound ( 0 , count , 65535 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , bound ( 0 , color , 255 ) ) ;
MSG_WriteByte ( & sv . nqmulticast , ( int ) gravityflag ! = 0 ) ;
MSG_WriteCoord ( & sv . nqmulticast , randomveljitter ) ;
# endif
VectorAdd ( min , max , org ) ;
VectorScale ( org , 0.5 , org ) ;
SV_Multicast ( org , MULTICAST_PVS ) ;
2004-11-20 00:55:29 +00:00
}
// #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
void PF_te_bloodshower ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2005-05-26 12:55:34 +00:00
// [vector] min [vector] max [coord] explosionspeed [short] count
float * min = G_VECTOR ( OFS_PARM0 ) ;
float * max = G_VECTOR ( OFS_PARM1 ) ;
float speed = G_FLOAT ( OFS_PARM2 ) ;
float count = G_FLOAT ( OFS_PARM3 ) ;
vec3_t org ;
MSG_WriteByte ( & sv . multicast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . multicast , DPTE_BLOODSHOWER ) ;
// min
MSG_WriteCoord ( & sv . multicast , min [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , min [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , min [ 2 ] ) ;
// max
MSG_WriteCoord ( & sv . multicast , max [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , max [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , max [ 2 ] ) ;
// speed
MSG_WriteCoord ( & sv . multicast , speed ) ;
// count
MSG_WriteShort ( & sv . multicast , bound ( 0 , count , 65535 ) ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svc_temp_entity ) ;
MSG_WriteByte ( & sv . nqmulticast , DPTE_BLOODSHOWER ) ;
// min
MSG_WriteCoord ( & sv . nqmulticast , min [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , min [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , min [ 2 ] ) ;
// max
MSG_WriteCoord ( & sv . nqmulticast , max [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , max [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , max [ 2 ] ) ;
// speed
MSG_WriteCoord ( & sv . nqmulticast , speed ) ;
// count
MSG_WriteShort ( & sv . nqmulticast , bound ( 0 , count , 65535 ) ) ;
# endif
VectorAdd ( min , max , org ) ;
VectorScale ( org , 0.5 , org ) ;
SV_Multicast ( org , MULTICAST_PVS ) ; //fixme: should this be phs instead?
2004-11-20 00:55:29 +00:00
}
//DP_SV_EFFECT
2004-11-21 07:31:26 +00:00
//void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
2004-11-20 00:55:29 +00:00
void PF_effect ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-11-21 07:31:26 +00:00
float * org = G_VECTOR ( OFS_PARM0 ) ;
char * name = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
float startframe = G_FLOAT ( OFS_PARM2 ) ;
float endframe = G_FLOAT ( OFS_PARM3 ) ;
float framerate = G_FLOAT ( OFS_PARM4 ) ;
int index = SV_ModelIndex ( name ) ;
if ( startframe > 255 | | index > 255 )
{
MSG_WriteByte ( & sv . multicast , svcqw_effect2 ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
MSG_WriteShort ( & sv . multicast , index ) ;
MSG_WriteShort ( & sv . multicast , startframe ) ;
MSG_WriteByte ( & sv . multicast , endframe ) ;
MSG_WriteByte ( & sv . multicast , framerate ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svcnq_effect2 ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 2 ] ) ;
MSG_WriteShort ( & sv . nqmulticast , index ) ;
MSG_WriteShort ( & sv . nqmulticast , startframe ) ;
MSG_WriteByte ( & sv . nqmulticast , endframe ) ;
MSG_WriteByte ( & sv . nqmulticast , framerate ) ;
# endif
}
else
{
MSG_WriteByte ( & sv . multicast , svcqw_effect ) ;
MSG_WriteCoord ( & sv . multicast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . multicast , org [ 2 ] ) ;
MSG_WriteByte ( & sv . multicast , index ) ;
MSG_WriteByte ( & sv . multicast , startframe ) ;
MSG_WriteByte ( & sv . multicast , endframe ) ;
MSG_WriteByte ( & sv . multicast , framerate ) ;
# ifdef NQPROT
MSG_WriteByte ( & sv . nqmulticast , svcnq_effect ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 0 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 1 ] ) ;
MSG_WriteCoord ( & sv . nqmulticast , org [ 2 ] ) ;
MSG_WriteByte ( & sv . nqmulticast , index ) ;
MSG_WriteByte ( & sv . nqmulticast , startframe ) ;
MSG_WriteByte ( & sv . nqmulticast , endframe ) ;
MSG_WriteByte ( & sv . nqmulticast , framerate ) ;
# endif
}
SV_Multicast ( org , MULTICAST_PVS ) ;
}
//DP_TE_PLASMABURN
//void(vector org) te_plasmaburn = #433;
void PF_te_plasmaburn ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
float * org = G_VECTOR ( OFS_PARM0 ) ;
SV_point_tempentity ( org , 75 , 0 ) ;
2004-11-20 00:55:29 +00:00
}
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
void PF_ForceInfoKey ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e ;
int e1 ;
char * value ;
char * key ;
e = G_EDICT ( prinst , OFS_PARM0 ) ;
e1 = NUM_FOR_EDICT ( prinst , e ) ;
key = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
value = PR_GetStringOfs ( prinst , OFS_PARM2 ) ;
G_FLOAT ( OFS_RETURN ) = 0 ;
if ( e1 = = 0 )
{ //localinfo
Info_SetValueForKey ( localinfo , key , value , MAX_LOCALINFO_STRING ) ;
G_FLOAT ( OFS_RETURN ) = 2 ;
}
else if ( e1 < = sv . allocated_client_slots )
{ //woo. we found a client.
2005-03-07 08:55:30 +00:00
Info_SetValueForStarKey ( svs . clients [ e1 - 1 ] . userinfo , key , value , sizeof ( svs . clients [ e1 - 1 ] . userinfo ) ) ;
2004-08-23 00:15:46 +00:00
SV_ExtractFromUserinfo ( & svs . clients [ e1 - 1 ] ) ;
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , e1 - 1 ) ;
MSG_WriteString ( & sv . reliable_datagram , key ) ;
MSG_WriteString ( & sv . reliable_datagram , Info_ValueForKey ( svs . clients [ e1 - 1 ] . userinfo , key ) ) ;
2005-01-17 17:46:49 +00:00
if ( ! strcmp ( key , " *spectator " ) )
svs . clients [ e1 - 1 ] . spectator = ! ! atoi ( value ) ;
2004-08-23 00:15:46 +00:00
G_FLOAT ( OFS_RETURN ) = 1 ;
}
else
Con_DPrintf ( " PF_ForceInfoKey: not world or client \n " ) ;
}
2004-08-31 23:58:18 +00:00
/*
= = = = = = = = = = = = = = = = =
PF_setcolors
sets the color of a client and broadcasts the update to all connected clients
setcolors ( clientent , value )
= = = = = = = = = = = = = = = = =
*/
//from lh
void PF_setcolors ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
client_t * client ;
int entnum , i ;
char number [ 8 ] ;
entnum = G_EDICTNUM ( prinst , OFS_PARM0 ) ;
i = G_FLOAT ( OFS_PARM1 ) ;
if ( entnum < 1 | | entnum > MAX_CLIENTS )
{
Con_Printf ( " tried to setcolor a non-client \n " ) ;
return ;
}
client = & svs . clients [ entnum - 1 ] ;
2005-03-28 00:11:59 +00:00
client - > edict - > v - > team = ( i & 15 ) + 1 ;
2004-09-07 18:28:25 +00:00
# ifdef NQPROT
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . nqreliable_datagram , svc_updatecolors ) ;
MSG_WriteByte ( & sv . nqreliable_datagram , entnum - 1 ) ;
MSG_WriteByte ( & sv . nqreliable_datagram , i ) ;
2004-09-07 18:28:25 +00:00
# endif
2004-08-31 23:58:18 +00:00
sprintf ( number , " %i " , i > > 4 ) ;
if ( ! strcmp ( number , Info_ValueForKey ( client - > userinfo , " topcolor " ) ) )
{
2005-03-07 08:55:30 +00:00
Info_SetValueForKey ( client - > userinfo , " topcolor " , number , sizeof ( client - > userinfo ) ) ;
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , entnum - 1 ) ;
MSG_WriteString ( & sv . reliable_datagram , " topcolor " ) ;
MSG_WriteString ( & sv . reliable_datagram , number ) ;
}
sprintf ( number , " %i " , i & 15 ) ;
if ( ! strcmp ( number , Info_ValueForKey ( client - > userinfo , " bottomcolor " ) ) )
{
2005-03-07 08:55:30 +00:00
Info_SetValueForKey ( client - > userinfo , " bottomcolor " , number , sizeof ( client - > userinfo ) ) ;
2004-08-31 23:58:18 +00:00
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , entnum - 1 ) ;
MSG_WriteString ( & sv . reliable_datagram , " bottomcolor " ) ;
MSG_WriteString ( & sv . reliable_datagram , number ) ;
}
SV_ExtractFromUserinfo ( client ) ;
}
2004-09-13 02:22:02 +00:00
static client_t * DirectSplit ( client_t * cl , int svc , int svclen )
2004-09-08 05:09:33 +00:00
{
2004-09-13 02:22:02 +00:00
if ( cl - > controller )
{ //this is a slave client.
//find the right number and send.
client_t * sp ;
int pnum = 0 ;
for ( sp = cl - > controller ; sp ; sp = sp - > controlled )
{
if ( sp = = cl )
break ;
pnum + + ;
}
sp = cl - > controller ;
ClientReliableWrite_Begin ( sp , svc_choosesplitclient , 2 + svclen ) ;
ClientReliableWrite_Byte ( sp , pnum ) ;
ClientReliableWrite_Byte ( sp , svc ) ;
return sp ;
}
else
{
ClientReliableWrite_Begin ( cl , svc , svclen ) ;
return cl ;
}
2004-09-08 05:09:33 +00:00
}
2004-08-31 23:58:18 +00:00
static void ParamNegateFix ( float * xx , float * yy , int Zone )
{
float x , y ;
x = xx [ 0 ] ;
y = yy [ 0 ] ;
if ( Zone = = SL_ORG_CC | | SL_ORG_CW = = Zone | | SL_ORG_CE = = Zone )
y = y + 8000 ;
if ( Zone = = SL_ORG_CC | | SL_ORG_CN = = Zone | | SL_ORG_CS = = Zone )
x = x + 8000 ;
xx [ 0 ] = x ;
yy [ 0 ] = y ;
}
void PF_ShowPic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * slot = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * picname = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
float x = G_FLOAT ( OFS_PARM2 ) ;
float y = G_FLOAT ( OFS_PARM3 ) ;
float zone = G_FLOAT ( OFS_PARM4 ) ;
int entnum ;
2004-09-08 05:09:33 +00:00
client_t * cl ;
2004-08-31 23:58:18 +00:00
ParamNegateFix ( & x , & y , zone ) ;
if ( * prinst - > callargc = = 6 )
{ //to a single client
entnum = G_EDICTNUM ( prinst , OFS_PARM5 ) - 1 ;
if ( entnum < 0 | | entnum > = sv . allocated_client_slots )
2005-02-28 07:16:19 +00:00
PR_RunError ( prinst , " WriteDest: not a client " ) ;
2004-08-31 23:58:18 +00:00
if ( ! ( svs . clients [ entnum ] . fteprotocolextensions & PEXT_SHOWPIC ) )
return ; //need an extension for this. duh.
2004-09-13 02:22:02 +00:00
cl = DirectSplit ( & svs . clients [ entnum ] , svc_showpic , 8 + strlen ( slot ) + strlen ( picname ) ) ;
ClientReliableWrite_Byte ( cl , zone ) ;
ClientReliableWrite_String ( cl , slot ) ;
ClientReliableWrite_String ( cl , picname ) ;
ClientReliableWrite_Short ( cl , x ) ;
ClientReliableWrite_Short ( cl , y ) ;
2004-08-31 23:58:18 +00:00
}
else
{
2004-09-13 02:22:02 +00:00
* prinst - > callargc = 6 ;
for ( entnum = 0 ; entnum < sv . allocated_client_slots ; entnum + + )
{
G_INT ( OFS_PARM5 ) = EDICT_TO_PROG ( prinst , EDICT_NUM ( prinst , entnum + 1 ) ) ;
PF_ShowPic ( prinst , pr_globals ) ;
}
2004-08-31 23:58:18 +00:00
}
} ;
void PF_HidePic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
2004-09-13 02:22:02 +00:00
client_t * cl ;
2004-08-31 23:58:18 +00:00
char * slot = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
int entnum ;
if ( * prinst - > callargc = = 2 )
{ //to a single client
entnum = G_EDICTNUM ( prinst , OFS_PARM1 ) - 1 ;
if ( entnum < 0 | | entnum > = sv . allocated_client_slots )
2005-02-28 07:16:19 +00:00
PR_RunError ( prinst , " WriteDest: not a client " ) ;
2004-08-31 23:58:18 +00:00
if ( ! ( svs . clients [ entnum ] . fteprotocolextensions & PEXT_SHOWPIC ) )
return ; //need an extension for this. duh.
2004-09-13 02:22:02 +00:00
cl = DirectSplit ( & svs . clients [ entnum ] , svc_hidepic , 2 + strlen ( slot ) ) ;
ClientReliableWrite_String ( cl , slot ) ;
2004-08-31 23:58:18 +00:00
}
else
{
2004-09-13 02:22:02 +00:00
* prinst - > callargc = 2 ;
for ( entnum = 0 ; entnum < sv . allocated_client_slots ; entnum + + )
{
G_INT ( OFS_PARM1 ) = EDICT_TO_PROG ( prinst , EDICT_NUM ( prinst , entnum + 1 ) ) ;
PF_HidePic ( prinst , pr_globals ) ;
}
2004-08-31 23:58:18 +00:00
}
} ;
void PF_MovePic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * slot = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
float x = G_FLOAT ( OFS_PARM1 ) ;
float y = G_FLOAT ( OFS_PARM2 ) ;
float zone = G_FLOAT ( OFS_PARM3 ) ;
int entnum ;
2004-09-13 02:22:02 +00:00
client_t * cl ;
2004-08-31 23:58:18 +00:00
ParamNegateFix ( & x , & y , zone ) ;
if ( * prinst - > callargc = = 5 )
{ //to a single client
entnum = G_EDICTNUM ( prinst , OFS_PARM4 ) - 1 ;
if ( entnum < 0 | | entnum > = sv . allocated_client_slots )
2005-02-28 07:16:19 +00:00
PR_RunError ( prinst , " WriteDest: not a client " ) ;
2004-08-31 23:58:18 +00:00
if ( ! ( svs . clients [ entnum ] . fteprotocolextensions & PEXT_SHOWPIC ) )
return ; //need an extension for this. duh.
2004-09-13 02:22:02 +00:00
cl = DirectSplit ( & svs . clients [ entnum ] , svc_movepic , 6 + strlen ( slot ) ) ;
ClientReliableWrite_String ( cl , slot ) ;
ClientReliableWrite_Byte ( cl , zone ) ;
ClientReliableWrite_Short ( cl , x ) ;
ClientReliableWrite_Short ( cl , y ) ;
2004-08-31 23:58:18 +00:00
}
else
{
2004-09-13 02:22:02 +00:00
* prinst - > callargc = 5 ;
for ( entnum = 0 ; entnum < sv . allocated_client_slots ; entnum + + )
{
G_INT ( OFS_PARM4 ) = EDICT_TO_PROG ( prinst , EDICT_NUM ( prinst , entnum + 1 ) ) ;
PF_MovePic ( prinst , pr_globals ) ;
}
2004-08-31 23:58:18 +00:00
}
} ;
void PF_ChangePic ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * slot = PR_GetStringOfs ( prinst , OFS_PARM0 ) ;
char * newpic = PR_GetStringOfs ( prinst , OFS_PARM1 ) ;
int entnum ;
2004-09-13 02:22:02 +00:00
client_t * cl ;
2004-08-31 23:58:18 +00:00
if ( * prinst - > callargc = = 3 )
{ //to a single client
entnum = G_EDICTNUM ( prinst , OFS_PARM2 ) - 1 ;
if ( entnum < 0 | | entnum > = sv . allocated_client_slots )
2005-02-28 07:16:19 +00:00
PR_RunError ( prinst , " WriteDest: not a client " ) ;
2004-08-31 23:58:18 +00:00
if ( ! ( svs . clients [ entnum ] . fteprotocolextensions & PEXT_SHOWPIC ) )
return ; //need an extension for this. duh.
2004-09-13 02:22:02 +00:00
cl = DirectSplit ( & svs . clients [ entnum ] , svc_updatepic , 3 + strlen ( slot ) + strlen ( newpic ) ) ;
ClientReliableWrite_String ( cl , slot ) ;
ClientReliableWrite_String ( cl , newpic ) ;
2004-08-31 23:58:18 +00:00
}
else
{
2004-09-13 02:22:02 +00:00
* prinst - > callargc = 3 ;
for ( entnum = 0 ; entnum < sv . allocated_client_slots ; entnum + + )
{
G_INT ( OFS_PARM2 ) = EDICT_TO_PROG ( prinst , EDICT_NUM ( prinst , entnum + 1 ) ) ;
PF_ChangePic ( prinst , pr_globals ) ;
}
2004-08-31 23:58:18 +00:00
}
}
2004-11-17 17:52:18 +00:00
typedef struct {
int ident ;
int version ;
char name [ MAX_QPATH ] ;
int flags ; //Does anyone know what these are?
int numFrames ;
int numTags ;
int numSurfaces ;
int numSkins ;
int ofsFrames ;
int ofsTags ;
int ofsSurfaces ;
int ofsEnd ;
} md3Header_t ;
typedef struct {
char name [ MAX_QPATH ] ;
vec3_t org ;
float ang [ 3 ] [ 3 ] ;
} md3tag_t ;
md3tag_t * SV_GetTags ( int modelindex , int * tagcount )
{
md3Header_t * file ;
file = ( md3Header_t * ) COM_LoadTempFile ( sv . model_precache [ modelindex ] ) ;
if ( ! file )
{
Con_Printf ( " setattachment: \" %s \" is missing \n " , sv . model_precache [ modelindex ] ) ;
return NULL ;
}
if ( file - > ident ! = MD3_IDENT )
{
Con_DPrintf ( " setattachment: not an md3 (%s) \n " , sv . model_precache [ modelindex ] ) ;
return NULL ;
}
* tagcount = file - > numTags ;
return ( md3tag_t * ) ( ( char * ) file + file - > ofsTags ) ;
}
2004-10-10 06:32:29 +00:00
void PF_setattachment ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
edict_t * e = G_EDICT ( prinst , OFS_PARM0 ) ;
edict_t * tagentity = G_EDICT ( prinst , OFS_PARM1 ) ;
char * tagname = PR_GetStringOfs ( prinst , OFS_PARM2 ) ;
eval_t * te ;
eval_t * ti ;
2004-11-17 17:52:18 +00:00
int i , modelindex ;
md3tag_t * model ;
int tagcount ;
2004-10-10 06:32:29 +00:00
te = prinst - > GetEdictFieldValue ( prinst , e , " tag_entity " , NULL ) ;
ti = prinst - > GetEdictFieldValue ( prinst , e , " tag_index " , NULL ) ;
e - > tagent = tagentity - > entnum ;
e - > tagindex = 0 ;
if ( tagentity ! = sv . edicts & & tagname & & tagname [ 0 ] )
{
2005-03-28 00:11:59 +00:00
modelindex = ( int ) tagentity - > v - > modelindex ;
2004-11-17 17:52:18 +00:00
if ( modelindex > 0 & & modelindex < MAX_MODELS & & ( model = SV_GetTags ( modelindex , & tagcount ) ) )
2004-10-10 06:32:29 +00:00
{
2004-11-17 17:52:18 +00:00
for ( i = 0 ; i < tagcount ; i + + )
{
if ( ! strcmp ( tagname , model [ i ] . name ) )
{
e - > tagindex = i + 1 ;
break ;
}
}
if ( e - > tagindex = = 0 )
Con_DPrintf ( " setattachment(edict %i, edict %i, string \" %s \" ): tried to find tag named \" %s \" on entity %i (model \" %s \" ) but could not find it \n " , NUM_FOR_EDICT ( prinst , e ) , NUM_FOR_EDICT ( prinst , tagentity ) , tagname , tagname , NUM_FOR_EDICT ( prinst , tagentity ) , model - > name ) ;
2004-10-10 06:32:29 +00:00
}
else
2004-11-17 17:52:18 +00:00
Con_DPrintf ( " setattachment(edict %i, edict %i, string \" %s \" ): tried to find tag named \" %s \" on entity %i but it has no model \n " , NUM_FOR_EDICT ( prinst , e ) , NUM_FOR_EDICT ( prinst , tagentity ) , tagname , tagname , NUM_FOR_EDICT ( prinst , tagentity ) ) ;
2004-10-10 06:32:29 +00:00
}
//fix me, move to somewhere nicer.
MSG_WriteByte ( & sv . multicast , svc_setattachment ) ;
MSG_WriteShort ( & sv . multicast , e - > entnum ) ;
MSG_WriteShort ( & sv . multicast , e - > tagent ) ;
MSG_WriteShort ( & sv . multicast , e - > tagindex ) ;
SV_MulticastProtExt ( vec3_origin , MULTICAST_ALL_R , 0xffffffff , PEXT_SETATTACHMENT , 0 ) ;
if ( te )
te - > edict = EDICT_TO_PROG ( prinst , EDICT_NUM ( prinst , e - > tagent ) ) ;
if ( ti )
te - > _float = e - > tagindex ;
}
2004-08-31 23:58:18 +00:00
2005-02-28 07:16:19 +00:00
void PF_clientstat ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
char * name = PF_VarString ( prinst , 2 , pr_globals ) ;
SV_QCStat ( G_FLOAT ( OFS_PARM0 ) , name , G_FLOAT ( OFS_PARM1 ) ) ;
}
void PF_runclientphys ( progfuncs_t * prinst , struct globalvars_s * pr_globals )
{
pmove . numphysent = 1 ;
pmove . physents [ 0 ] . model = sv . worldmodel ;
// AddLinksToPmove ( sv_areanodes );
2005-03-20 02:57:11 +00:00
PM_PlayerMove ( sv . gamespeed ) ;
2005-02-28 07:16:19 +00:00
}
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
BuiltinList_t BuiltinList [ ] = { //nq qw h2 ebfs
2004-08-31 23:58:18 +00:00
{ " fixme " , PF_Fixme , 0 , 0 , 0 } ,
{ " ignore " , PF_Ignore , 0 , 0 , 0 } ,
2004-08-23 00:15:46 +00:00
{ " makevectors " , PF_makevectors , 1 , 1 , 1 } , // void(entity e) makevectors = #1;
{ " setorigin " , PF_setorigin , 2 , 2 , 2 } , // void(entity e, vector o) setorigin = #2;
{ " setmodel " , PF_setmodel , 3 , 3 , 3 } , // void(entity e, string m) setmodel = #3;
{ " setsize " , PF_setsize , 4 , 4 , 4 } , // void(entity e, vector min, vector max) setsize = #4;
// {"qtest_setabssize",NULL, 5},
{ " lightstylestatic " , PF_lightstylestatic , 0 , 0 , 5 , 5 } ,
{ " break " , PF_break , 6 , 6 , 6 } , // void() break = #6;
{ " random " , PF_random , 7 , 7 , 7 } , // float() random = #7;
{ " sound " , PF_sound , 8 , 8 , 8 } , // void(entity e, float chan, string samp) sound = #8;
{ " normalize " , PF_normalize , 9 , 9 , 9 } , // vector(vector v) normalize = #9;
{ " error " , PF_error , 10 , 10 , 10 } , // void(string e) error = #10;
{ " objerror " , PF_objerror , 11 , 11 , 11 } , // void(string e) objerror = #11;
{ " vlen " , PF_vlen , 12 , 12 , 12 } , // float(vector v) vlen = #12;
{ " vectoyaw " , PF_vectoyaw , 13 , 13 , 13 } , // float(vector v) vectoyaw = #13;
{ " spawn " , PF_Spawn , 14 , 14 , 14 } , // entity() spawn = #14;
{ " remove " , PF_Remove , 15 , 15 , 15 } , // void(entity e) remove = #15;
{ " traceline " , PF_traceline , 16 , 16 , 16 } , // float(vector v1, vector v2, float tryents) traceline = #16;
{ " checkclient " , PF_checkclient , 17 , 17 , 17 } , // entity() clientlist = #17;
2004-11-21 07:31:26 +00:00
{ " find " , PF_FindString , 18 , 18 , 18 } , // entity(entity start, .string fld, string match) find = #18;
2004-08-23 00:15:46 +00:00
{ " precache_sound " , PF_precache_sound , 19 , 19 , 19 } , // void(string s) precache_sound = #19;
{ " precache_model " , PF_precache_model , 20 , 20 , 20 } , // void(string s) precache_model = #20;
{ " stuffcmd " , PF_stuffcmd , 21 , 21 , 21 } , // void(entity client, string s)stuffcmd = #21;
{ " findradius " , PF_findradius , 22 , 22 , 22 } , // entity(vector org, float rad) findradius = #22;
{ " bprint " , PF_bprint , 23 , 23 , 23 } , // void(string s) bprint = #23;
//FIXME: distinguish between qw and nq parameters here?
{ " sprint " , PF_sprint , 24 , 24 , 24 } , // void(entity client, string s) sprint = #24;
2005-03-07 08:55:30 +00:00
{ " dprint " , PF_dprint , 25 , 0 , 25 } , // void(string s) dprint = #25;
2005-05-13 10:42:48 +00:00
{ " print " , PF_print , 0 , 25 , 0 } , // void(string s) print = #25;
2004-08-23 00:15:46 +00:00
{ " ftos " , PF_ftos , 26 , 26 , 26 } , // void(string s) ftos = #26;
{ " vtos " , PF_vtos , 27 , 27 , 27 } , // void(string s) vtos = #27;
{ " coredump " , PF_coredump , 28 , 28 , 28 } , //28
{ " traceon " , PF_traceon , 29 , 29 , 29 } , //29
{ " traceoff " , PF_traceoff , 30 , 30 , 30 } , //30
{ " eprint " , PF_eprint , 31 , 31 , 31 } , //31 // void(entity e) debug print an entire entity
{ " walkmove " , PF_walkmove , 32 , 32 , 32 } , //32 // float(float yaw, float dist) walkmove
{ " tracearea " , PF_traceboxh2 , 0 , 0 , 33 } , //33 //
// {"qtest_flymove", NULL, 33}, //vector
{ " droptofloor " , PF_droptofloor , 34 , 34 , 34 } , //34
{ " lightstyle " , PF_lightstyle , 35 , 35 , 35 } , //35
{ " rint " , PF_rint , 36 , 36 , 36 } , //36
{ " floor " , PF_floor , 37 , 37 , 37 } , //37
{ " ceil " , PF_ceil , 38 , 38 , 38 } , //38
// {"qtest_canreach", NULL, 39},
{ " checkbottom " , PF_checkbottom , 40 , 40 , 40 } , //40
{ " pointcontents " , PF_pointcontents , 41 , 41 , 41 } , //41
// {"qtest_stopsound", NULL, 42},
{ " fabs " , PF_fabs , 43 , 43 , 43 } , //43
{ " aim " , PF_aim , 44 , 44 , 44 } , //44
{ " cvar " , PF_cvar , 45 , 45 , 45 } , //45
{ " localcmd " , PF_localcmd , 46 , 46 , 46 } , //46
{ " nextent " , PF_nextent , 47 , 47 , 47 } , //47
{ " particle " , PF_particle , 48 , 0 , 48 , 48 } , //48 nq readded. This isn't present in QW protocol (fte added it back).
{ " changeyaw " , PF_changeyaw , 49 , 49 , 49 } , //49
// {"qtest_precacheitem", NULL, 50}, //1 1
{ " vhlen " , PF_vhlen , 0 , 0 , 50 } , //49
{ " vectoangles " , PF_vectoangles , 51 , 51 , 51 } , //51
{ " writebyte " , PF_WriteByte , 52 , 52 , 52 } , //52
{ " writechar " , PF_WriteChar , 53 , 53 , 53 } , //53
{ " writeshort " , PF_WriteShort , 54 , 54 , 54 } , //54
{ " writelong " , PF_WriteLong , 55 , 55 , 55 } , //55
{ " writecoord " , PF_WriteCoord , 56 , 56 , 56 } , //56
{ " writeangle " , PF_WriteAngle , 57 , 57 , 57 } , //57
{ " writestring " , PF_WriteString , 58 , 58 , 58 } , //58
{ " writeentity " , PF_WriteEntity , 59 , 59 , 59 } , //59
2005-05-08 17:03:19 +00:00
{ " swritebyte " , PF_Single_WriteByte } , //52
{ " swritechar " , PF_Single_WriteChar } , //53
{ " swriteshort " , PF_Single_WriteShort } , //54
{ " swritelong " , PF_Single_WriteLong } , //55
{ " swritecoord " , PF_Single_WriteCoord } , //56
{ " swriteangle " , PF_Single_WriteAngle } , //57
{ " swritestring " , PF_Single_WriteString } , //58
{ " swriteentity " , PF_Single_WriteEntity } ,
{ " bwritebyte " , PF_Broadcast_WriteByte } , //59
{ " bwritechar " , PF_Broadcast_WriteChar } , //60
{ " bwriteshort " , PF_Broadcast_WriteShort } , //61
{ " bwritelong " , PF_Broadcast_WriteLong } , //62
{ " bwritecoord " , PF_Broadcast_WriteCoord } , //63
{ " bwriteangle " , PF_Broadcast_WriteAngle } , //64
{ " bwritestring " , PF_Broadcast_WriteString } , //65
{ " bwriteentity " , PF_Broadcast_WriteEntity } , //66
2005-03-07 08:55:30 +00:00
{ " printfloat " , PF_printf , 0 , 0 , 60 } , //60
2004-08-23 00:15:46 +00:00
{ " sin " , PF_Sin , 0 , 0 , 62 , 60 } , //60
{ " cos " , PF_Cos , 0 , 0 , 61 , 61 } , //61
{ " sqrt " , PF_Sqrt , 0 , 0 , 84 , 62 } , //62
{ " AdvanceFrame " , PF_AdvanceFrame , 0 , 0 , 63 , 0 } ,
2005-03-07 08:55:30 +00:00
{ " printvec " , PF_printv , 0 , 0 , 64 , 0 } , //64
2004-08-23 00:15:46 +00:00
{ " RewindFrame " , PF_RewindFrame , 0 , 0 , 65 , 0 } ,
{ " particleexplosion " , PF_particleexplosion , 0 , 0 , 81 , 0 } ,
{ " movestep " , PF_movestep , 0 , 0 , 82 , 0 } ,
{ " advanceweaponframe " , PF_advanceweaponframe , 0 , 0 , 83 , 0 } ,
{ " setclass " , PF_setclass , 0 , 0 , 66 , 0 } ,
2004-10-13 06:37:44 +00:00
{ " changepitch " , PF_changepitch , 0 , 0 , 0 , 63 } ,
{ " tracetoss " , PF_TraceToss , 0 , 0 , 0 , 64 } ,
{ " etos " , PF_etos , 0 , 0 , 0 , 65 } ,
2004-08-23 00:15:46 +00:00
{ " movetogoal " , SV_MoveToGoal , 67 , 67 , 67 } , //67
{ " precache_file " , PF_precache_file , 68 , 68 , 68 } , //68
{ " makestatic " , PF_makestatic , 69 , 69 , 69 } , //69
{ " changelevel " , PF_changelevel , 70 , 70 , 70 } , //70
{ " lightstylevalue " , PF_lightstylevalue , 0 , 0 , 71 } , //70
{ " cvar_set " , PF_cvar_set , 72 , 72 , 72 } , //72
{ " centerprint " , PF_centerprint , 73 , 73 , 73 } , //73
{ " ambientsound " , PF_ambientsound , 74 , 74 , 74 } , //74
{ " precache_model2 " , PF_precache_model , 75 , 75 , 75 } , //75
{ " precache_sound2 " , PF_precache_sound , 76 , 76 , 76 } , //76 // precache_sound2 is different only for qcc
{ " precache_file2 " , PF_precache_file , 77 , 77 , 0 } , //77
{ " setspawnparms " , PF_setspawnparms , 78 , 78 , 78 } , //78
{ " plaque_draw " , PF_plaque_draw , 0 , 0 , 79 } , //79
{ " logfrag " , PF_logfrag , 0 , 79 , 0 } , //79
2004-08-31 23:58:18 +00:00
// Tomaz - QuakeC String Manipulation Begin
{ " tq_zone " , PF_dupstring , 0 , 0 , 0 , 79 } , //79
{ " tq_unzone " , PF_forgetstring , 0 , 0 , 0 , 80 } , //80
//stof
{ " tq_strcat " , PF_strcat , 0 , 0 , 0 , 82 } , //82
{ " tq_substring " , PF_substring , 0 , 0 , 0 , 83 } , //83
{ " tq_stof " , PF_stof , 0 , 0 , 0 , 84 } , //84
{ " tq_stov " , PF_stov , 0 , 0 , 0 , 85 } , //85
// Tomaz - QuakeC String Manipulation End
// Tomaz - QuakeC File System Begin (new mods use frik_file instead)
{ " tq_fopen " , PF_fopen , 0 , 0 , 0 , 86 } , // #86 float(string filename, float mode) fopen (QSG_FILE)
{ " tq_fclose " , PF_fclose , 0 , 0 , 0 , 87 } , // #87 void(float fhandle) fclose (QSG_FILE)
{ " tq_fgets " , PF_fgets , 0 , 0 , 0 , 88 } , // #88 string(float fhandle) fgets (QSG_FILE)
{ " tq_fputs " , PF_fputs , 0 , 0 , 0 , 89 } , // #89 void(float fhandle, string s) fputs (QSG_FILE)
// Tomaz - QuakeC File System End
{ " rain_go " , PF_rain_go , 0 , 0 , 80 } , //80
2004-08-23 00:15:46 +00:00
{ " infokey " , PF_infokey , 0 , 80 , 0 , 80 } , //80
{ " stof " , PF_stof , 0 , 81 , 0 , 81 } , //81
{ " multicast " , PF_multicast , 0 , 82 , 0 , 0 } , //82
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
//mvdsv (don't require ebfs usage in qw)
{ " executecommand " , PF_ExecuteCommand , 0 , 83 , 0 , 83 } , //83 //void() exec; please don't use.
{ " mvdtokenize " , PF_Tokenize , 0 , 84 , 0 , 84 } , //84 //void(string str) tokanize;
{ " mvdargc " , PF_ArgC , 0 , 85 , 0 , 85 } , //85 //float() argc;
{ " mvdargv " , PF_ArgV , 0 , 86 , 0 , 86 } , //86 //string(float num) argv;
2004-09-13 02:22:02 +00:00
//mvd commands
//some of these are a little iffy.
//we support them for mvdsv compatability but some of them look very hacky.
//these ones are not honoured with numbers, but can be used via the proper means.
2004-10-19 16:10:14 +00:00
{ " teamfield " , PF_teamfield , 0 , 0 , 0 , 0 } ,
{ " substr " , PF_substr , 0 , 0 , 0 , 0 } ,
{ " mvdstrcat " , PF_strcat , 0 , 0 , 0 , 0 } ,
{ " mvdstrlen " , PF_strlen , 0 , 0 , 0 , 0 } ,
{ " str2byte " , PF_str2byte , 0 , 0 , 0 , 0 } ,
{ " str2short " , PF_str2short , 0 , 0 , 0 , 0 } ,
2004-09-13 02:22:02 +00:00
{ " mvdnewstr " , PF_newstring , 0 , 0 , 0 , 0 } ,
{ " mvdfreestr " , PF_forgetstring , 0 , 0 , 0 , 0 } ,
2004-10-19 16:10:14 +00:00
{ " conprint " , PF_conprint , 0 , 0 , 0 , 0 } ,
{ " readcmd " , PF_readcmd , 0 , 0 , 0 , 0 } ,
2004-09-13 02:22:02 +00:00
{ " mvdstrcpy " , PF_MVDSV_strcpy , 0 , 0 , 0 , 0 } ,
2004-10-19 16:10:14 +00:00
{ " strstr " , PF_strstr , 0 , 0 , 0 , 0 } ,
2004-09-13 02:22:02 +00:00
{ " mvdstrncpy " , PF_MVDSV_strncpy , 0 , 0 , 0 , 0 } ,
2004-10-19 16:10:14 +00:00
{ " log " , PF_log , 0 , 0 , 0 , 0 } ,
2004-08-23 00:15:46 +00:00
// {"redirectcmd", PF_redirectcmd, 0, 0, 0, 101},
2004-11-17 17:52:18 +00:00
{ " mvdcalltimeofday " , PF_calltimeofday , 0 , 0 , 0 , 102 } ,
2004-08-23 00:15:46 +00:00
{ " forcedemoframe " , PF_forcedemoframe , 0 , 0 , 0 , 103 } ,
//end of mvdsv
{ " setpuzzlemodel " , PF_set_puzzle_model , 0 , 0 , 87 , 0 } ,
{ " starteffect " , PF_starteffect , 0 , 0 , 88 , 0 } , //FIXME
{ " endeffect " , PF_endeffect , 0 , 0 , 89 , 0 } , //FIXME
{ " getstring " , PF_getstring , 0 , 0 , 92 , 0 } , //FIXME
{ " spawntemp " , PF_spawn_temp , 0 , 0 , 93 , 0 } ,
{ " v_factor " , PF_v_factor , 0 , 0 , 94 , 0 } ,
{ " v_factorrange " , PF_v_factorrange , 0 , 0 , 95 , 0 } ,
{ " precache_puzzle_model " , PF_precache_puzzle_model , 0 , 0 , 90 , 0 } ,
{ " concatv " , PF_concatv , 0 , 0 , 91 , 0 } ,
{ " precache_sound3 " , PF_precache_sound , 0 , 0 , 96 , 0 } ,
{ " precache_model3 " , PF_precache_model , 0 , 0 , 97 , 0 } , //please don't use...
{ " matchangletoslope " , PF_matchAngleToSlope , 0 , 0 , 99 , 0 } ,
{ " precache_sound4 " , PF_precache_sound , 0 , 0 , 101 , 0 } ,
{ " precache_model4 " , PF_precache_model , 0 , 0 , 102 , 0 } ,
{ " precache_file4 " , PF_precache_file , 0 , 0 , 103 , 0 } ,
2005-02-28 07:16:19 +00:00
{ " stopsound " , PF_StopSound , 0 , 0 , 106 , 0 } ,
2004-08-23 00:15:46 +00:00
{ " precache_model4 " , PF_precache_model , 0 , 0 , 116 , 0 } , //please don't use...
{ " precache_sound4 " , PF_precache_sound , 0 , 0 , 117 , 0 } ,
{ " tracebox " , PF_traceboxdp , 0 , 0 , 0 , 90 } ,
{ " randomvec " , PF_randomvec , 0 , 0 , 0 , 91 } ,
{ " registercvar " , PF_registercvar , 0 , 0 , 0 , 93 } ,
{ " min " , PF_min , 0 , 0 , 0 , 94 } , // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
{ " max " , PF_max , 0 , 0 , 0 , 95 } , // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
{ " bound " , PF_bound , 0 , 0 , 0 , 96 } , // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
{ " pow " , PF_pow , 0 , 0 , 0 , 97 } ,
2004-08-31 23:58:18 +00:00
{ " tj_cvar_string " , PF_cvar_string , 0 , 0 , 0 , 97 } , //telejano
//DP_QC_FINDFLOAT
2004-08-23 00:15:46 +00:00
{ " findfloat " , PF_FindFloat , 0 , 0 , 0 , 98 } , // #98 entity(entity start, float fld, float match) findfloat (DP_QC_FINDFLOAT)
{ " checkextension " , PF_checkextension , 99 , 99 , 0 , 99 } , // #99 //darkplaces system - query a string to see if the mod supports X Y and Z.
{ " builtin_find " , PF_builtinsupported , 100 , 100 , 0 , 100 } , // #100 //per builtin system.
{ " anglemod " , PF_anglemod , 0 , 0 , 0 , 102 } ,
{ " cvar_string " , PF_cvar_string , 0 , 0 , 0 , 103 } ,
2004-08-31 23:58:18 +00:00
//TEI_SHOWLMP2
{ " showpic " , PF_ShowPic , 0 , 0 , 0 , 104 } ,
{ " hidepic " , PF_HidePic , 0 , 0 , 0 , 105 } ,
{ " movepic " , PF_MovePic , 0 , 0 , 0 , 106 } ,
{ " changepic " , PF_ChangePic , 0 , 0 , 0 , 107 } ,
{ " showpicent " , PF_ShowPic , 0 , 0 , 0 , 108 } ,
{ " hidepicent " , PF_HidePic , 0 , 0 , 0 , 109 } ,
//End TEU_SHOWLMP2
2004-08-23 00:15:46 +00:00
//frik file
{ " fopen " , PF_fopen , 0 , 0 , 0 , 110 } , // #110 float(string filename, float mode) fopen (FRIK_FILE)
{ " fclose " , PF_fclose , 0 , 0 , 0 , 111 } , // #111 void(float fhandle) fclose (FRIK_FILE)
{ " fgets " , PF_fgets , 0 , 0 , 0 , 112 } , // #112 string(float fhandle) fgets (FRIK_FILE)
{ " fputs " , PF_fputs , 0 , 0 , 0 , 113 } , // #113 void(float fhandle, string s) fputs (FRIK_FILE)
{ " strlen " , PF_strlen , 0 , 0 , 0 , 114 } , // #114 float(string s) strlen (FRIK_FILE)
{ " strcat " , PF_strcat , 0 , 0 , 0 , 115 } , // #115 string(string s1, string s2) strcat (FRIK_FILE)
{ " substring " , PF_substring , 0 , 0 , 0 , 116 } , // #116 string(string s, float start, float length) substring (FRIK_FILE)
{ " stov " , PF_stov , 0 , 0 , 0 , 117 } , // #117 vector(string s) stov (FRIK_FILE)
{ " strzone " , PF_dupstring , 0 , 0 , 0 , 118 } , // #118 string(string s) strzone (FRIK_FILE)
{ " strunzone " , PF_forgetstring , 0 , 0 , 0 , 119 } , // #119 string(string s) strunzone (FRIK_FILE)
//end frikfile
2004-08-31 23:58:18 +00:00
//these are telejano's
{ " cvar_setf " , PF_cvar_setf , 0 , 0 , 0 , 176 } , // #176 void(string cvar, float val) cvar_setf
{ " localsound " , PF_LocalSound , 0 , 0 , 0 , 177 } , // #177
//end telejano
2004-08-23 00:15:46 +00:00
//fte extras
{ " getmodelindex " , PF_WeapIndex , 0 , 0 , 0 , 200 } ,
{ " externcall " , PF_externcall , 0 , 0 , 0 , 201 } ,
{ " addprogs " , PF_addprogs , 0 , 0 , 0 , 202 } ,
{ " externvalue " , PF_externvalue , 0 , 0 , 0 , 203 } ,
{ " externset " , PF_externset , 0 , 0 , 0 , 204 } ,
{ " externrefcall " , PF_externrefcall , 0 , 0 , 0 , 205 } ,
{ " instr " , PF_instr , 0 , 0 , 0 , 206 } ,
# ifdef Q2BSPS
{ " openportal " , PF_OpenPortal , 0 , 0 , 0 , 207 } ,
# endif
{ " RegisterTempEnt " , PF_RegisterTEnt , 0 , 0 , 0 , 208 } ,
{ " CustomTempEnt " , PF_CustomTEnt , 0 , 0 , 0 , 209 } ,
{ " fork " , PF_Fork , 0 , 0 , 0 , 210 } ,
{ " abort " , PF_Abort , 0 , 0 , 0 , 211 } ,
{ " sleep " , PF_Sleep , 0 , 0 , 0 , 212 } ,
{ " forceinfokey " , PF_ForceInfoKey , 0 , 0 , 0 , 213 } ,
# ifdef SVCHAT
{ " chat " , PF_chat , 0 , 0 , 0 , 214 } , // #214 void(string filename, float starttag, entity edict) SV_Chat (FTE_NPCCHAT)
# endif
2004-08-31 23:58:18 +00:00
//FTE_PEXT_HEXEN2
2004-08-23 00:15:46 +00:00
{ " particle2 " , PF_particle2 , 0 , 0 , 42 , 215 } ,
{ " particle3 " , PF_particle3 , 0 , 0 , 85 , 216 } ,
{ " particle4 " , PF_particle4 , 0 , 0 , 86 , 217 } ,
2004-11-20 00:55:29 +00:00
//EXT_DIMENSION_PLANES
2004-08-31 23:58:18 +00:00
{ " bitshift " , PF_bitshift , 0 , 0 , 0 , 218 } ,
//I guess this should go under DP_TE_STANDARDEFFECTBUILTINS...
{ " te_lightningblood " , PF_te_lightningblood , 0 , 0 , 0 , 219 } , // #219 te_lightningblood
2004-10-13 06:37:44 +00:00
2004-11-17 17:52:18 +00:00
{ " map_builtin " , PF_builtinsupported , 0 , 0 , 0 , 220 } , //like #100 - takes 2 args. arg0 is builtinname, 1 is number to map to.
2005-02-28 07:16:19 +00:00
//FTE_STRINGS
2004-11-17 17:52:18 +00:00
{ " strstrofs " , PF_strstrofs , 0 , 0 , 0 , 221 } ,
{ " str2chr " , PF_str2chr , 0 , 0 , 0 , 222 } ,
{ " chr2str " , PF_chr2str , 0 , 0 , 0 , 223 } ,
{ " strconv " , PF_strconv , 0 , 0 , 0 , 224 } ,
2005-03-07 08:55:30 +00:00
{ " strpad " , PF_strpad , 0 , 0 , 0 , 225 } , //will be moved
2004-11-17 17:52:18 +00:00
{ " infoadd " , PF_infoadd , 0 , 0 , 0 , 226 } ,
{ " infoget " , PF_infoget , 0 , 0 , 0 , 227 } ,
{ " strncmp " , PF_strncmp , 0 , 0 , 0 , 228 } ,
{ " strcasecmp " , PF_strcasecmp , 0 , 0 , 0 , 229 } ,
{ " strncasecmp " , PF_strncasecmp , 0 , 0 , 0 , 230 } ,
2005-02-28 07:16:19 +00:00
//END FTE_STRINGS
2004-11-17 17:52:18 +00:00
2005-02-28 07:16:19 +00:00
//FTE_CALLTIMEOFDAY
2004-11-17 17:52:18 +00:00
{ " calltimeofday " , PF_calltimeofday , 0 , 0 , 0 , 231 } ,
2005-02-28 07:16:19 +00:00
//EXT_CSQC
{ " clientstat " , PF_clientstat , 0 , 0 , 0 , 232 } ,
{ " runclientphys " , PF_runclientphys , 0 , 0 , 0 , 233 } ,
//END EXT_CSQC
2005-04-16 16:21:27 +00:00
{ " isbackbuffered " , PF_isbackbuffered , 0 , 0 , 0 , 234 } ,
2005-02-28 07:16:19 +00:00
2004-08-23 00:15:46 +00:00
//end fte extras
2004-08-31 23:58:18 +00:00
//DP extras
//DP_QC_COPYENTITY
2004-08-23 00:15:46 +00:00
{ " copyentity " , PF_copyentity , 0 , 0 , 0 , 400 } , // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2004-08-31 23:58:18 +00:00
//DP_SV_SETCOLOR
{ " setcolors " , PF_setcolors , 0 , 0 , 0 , 401 } , // #401 void(entity from, entity to) setcolors
//DP_QC_FINDCHAIN
2004-08-23 00:15:46 +00:00
{ " findchain " , PF_findchain , 0 , 0 , 0 , 402 } , // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN)
2004-08-31 23:58:18 +00:00
//DP_QC_FINDCHAINFLOAT
2004-08-23 00:15:46 +00:00
{ " findfloatchain " , PF_findchainfloat , 0 , 0 , 0 , 403 } , // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2004-11-20 00:55:29 +00:00
//DP_SV_EFFECT
{ " effect " , PF_effect , 0 , 0 , 0 , 404 } , // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
//DP_TE_BLOOD
2004-08-23 00:15:46 +00:00
{ " te_blood " , PF_te_blood , 0 , 0 , 0 , 405 } , // #405 te_blood
2004-11-20 00:55:29 +00:00
//DP_TE_BLOODSHOWER
{ " te_bloodshower " , PF_te_bloodshower , 0 , 0 , 0 , 406 } , // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
//DP_TE_PARTICLECUBE
{ " te_particlecube " , PF_te_particlecube , 0 , 0 , 0 , 408 } , // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
//DP_TE_SPARK
{ " te_spark " , PF_te_spark , 0 , 0 , 0 , 411 } , // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
//DP_TE_SMALLFLASH
{ " te_smallflash " , PF_te_smallflash , 0 , 0 , 0 , 416 } , // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
//DP_TE_CUSTOMFLASH
{ " te_customflash " , PF_te_customflash , 0 , 0 , 0 , 417 } , // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2004-08-31 23:58:18 +00:00
//DP_TE_STANDARDEFFECTBUILTINS
{ " te_gunshot " , PF_te_gunshot , 0 , 0 , 0 , 418 } , // #418 te_gunshot
{ " te_spike " , PF_te_spike , 0 , 0 , 0 , 419 } , // #419 te_spike
{ " te_superspike " , PF_te_superspike , 0 , 0 , 0 , 420 } , // #420 te_superspike
{ " te_explosion " , PF_te_explosion , 0 , 0 , 0 , 421 } , // #421 te_explosion
{ " te_tarexplosion " , PF_te_tarexplosion , 0 , 0 , 0 , 422 } , // #422 te_tarexplosion
{ " te_wizspike " , PF_te_wizspike , 0 , 0 , 0 , 423 } , // #423 te_wizspike
{ " te_knightspike " , PF_te_knightspike , 0 , 0 , 0 , 424 } , // #424 te_knightspike
{ " te_lavasplash " , PF_te_lavasplash , 0 , 0 , 0 , 425 } , // #425 te_lavasplash
{ " te_teleport " , PF_te_teleport , 0 , 0 , 0 , 426 } , // #426 te_teleport
{ " te_explosion2 " , PF_te_explosion2 , 0 , 0 , 0 , 427 } , // #427 te_explosion2
{ " te_lightning1 " , PF_te_lightning1 , 0 , 0 , 0 , 428 } , // #428 te_lightning1
{ " te_lightning2 " , PF_te_lightning2 , 0 , 0 , 0 , 429 } , // #429 te_lightning2
{ " te_lightning3 " , PF_te_lightning3 , 0 , 0 , 0 , 430 } , // #430 te_lightning3
{ " te_beam " , PF_te_beam , 0 , 0 , 0 , 431 } , // #431 te_beam
//DP_QC_VECTORVECTORS
2004-08-23 00:15:46 +00:00
{ " vectorvectors " , PF_vectorvectors , 0 , 0 , 0 , 432 } , // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2004-11-21 07:31:26 +00:00
{ " te_plasmaburn " , PF_te_plasmaburn , 0 , 0 , 0 , 433 } , // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2004-08-31 23:58:18 +00:00
//KRIMZON_SV_PARSECLIENTCOMMAND
2004-08-23 00:15:46 +00:00
{ " clientcommand " , PF_clientcommand , 0 , 0 , 0 , 440 } , // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
{ " tokenize " , PF_Tokenize , 0 , 0 , 0 , 441 } , // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
{ " argv " , PF_ArgV , 0 , 0 , 0 , 442 } , // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND
2004-10-10 06:32:29 +00:00
{ " setattachment " , PF_setattachment , 0 , 0 , 0 , 443 } , // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2005-04-16 16:21:27 +00:00
{ " search_begin " , PF_search_begin , 0 , 0 , 0 , 444 } ,
{ " search_end " , PF_search_end , 0 , 0 , 0 , 445 } ,
{ " search_getsize " , PF_search_getsize , 0 , 0 , 0 , 446 } ,
{ " search_getfilename " , PF_search_getfilename , 0 , 0 , 0 , 447 } ,
2004-09-13 02:22:02 +00:00
//DP_QC_CVAR_STRING
{ " dp_cvar_string " , PF_cvar_string , 0 , 0 , 0 , 448 } , // #448 string(float n) cvar_string
2004-10-13 06:37:44 +00:00
//DP_QC_FINDFLAGS
2004-11-17 17:52:18 +00:00
{ " findflags " , PF_FindFlags , 0 , 0 , 0 , 449 } , // #449 entity(entity start, .entity fld, float match) findflags
2004-10-13 06:37:44 +00:00
//DP_QC_FINDCHAINFLAGS
{ " findchainflags " , PF_findchainflags , 0 , 0 , 0 , 450 } , // #450 entity(.float fld, float match) findchainflags
2004-11-17 17:52:18 +00:00
{ " dropclient " , PF_dropclient , 0 , 0 , 0 , 453 } , // #453 void(entity player) dropclient
2004-08-23 00:15:46 +00:00
//end other peoples extras
2004-12-14 11:16:42 +00:00
{ " writestring2 " , PF_WriteString2 , 0 , 0 , 0 , 700 } , //writestring but without the null terminator. makes things a little nicer.
//don't exceed sizeof(pr_builtin)/sizeof(pr_builtin[0]) (currently 1024) without modifing the size of pr_builtin
2004-12-15 19:58:07 +00:00
{ NULL }
2004-08-23 00:15:46 +00:00
} ;
void PR_ResetBuiltins ( progstype_t type ) //fix all nulls to PF_FIXME and add any extras that have a big number.
{
int i ;
int builtincount [ sizeof ( pr_builtin ) / sizeof ( pr_builtin [ 0 ] ) ] ;
memset ( pr_builtin , 0 , sizeof ( pr_builtin ) ) ;
if ( type = = PROG_QW )
{
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
if ( BuiltinList [ i ] . qwnum )
{
if ( pr_builtin [ BuiltinList [ i ] . qwnum ] )
Sys_Error ( " Cannot assign builtin %s, already taken \n " , BuiltinList [ i ] . name ) ;
pr_builtin [ BuiltinList [ i ] . qwnum ] = BuiltinList [ i ] . bifunc ;
}
}
}
else if ( type = = PROG_H2 )
{
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
if ( BuiltinList [ i ] . h2num )
{
if ( pr_builtin [ BuiltinList [ i ] . h2num ] )
Sys_Error ( " Cannot assign builtin %s, already taken \n " , BuiltinList [ i ] . name ) ;
pr_builtin [ BuiltinList [ i ] . h2num ] = BuiltinList [ i ] . bifunc ;
}
}
}
else
{
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
if ( BuiltinList [ i ] . nqnum )
{
if ( pr_builtin [ BuiltinList [ i ] . nqnum ] )
Sys_Error ( " Cannot assign builtin %s, already taken \n " , BuiltinList [ i ] . name ) ;
pr_builtin [ BuiltinList [ i ] . nqnum ] = BuiltinList [ i ] . bifunc ;
}
}
}
2004-08-31 23:58:18 +00:00
memset ( builtincount , 0 , sizeof ( builtincount ) ) ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < pr_numbuiltins ; i + + ) //clean up nulls
{
if ( ! pr_builtin [ i ] )
{
pr_builtin [ i ] = PF_Fixme ;
}
else
builtincount [ i ] = 100 ;
}
2005-05-08 17:03:19 +00:00
if ( type = = PROG_PREREL )
{
pr_builtin [ 52 ] = PF_Single_WriteByte ;
pr_builtin [ 53 ] = PF_Single_WriteChar ;
pr_builtin [ 54 ] = PF_Single_WriteShort ;
pr_builtin [ 55 ] = PF_Single_WriteLong ;
pr_builtin [ 56 ] = PF_Single_WriteCoord ;
pr_builtin [ 57 ] = PF_Single_WriteAngle ;
pr_builtin [ 58 ] = PF_Single_WriteString ;
//lack of writeentity is intentional (prerel doesn't have it.
pr_builtin [ 59 ] = PF_Broadcast_WriteByte ;
pr_builtin [ 60 ] = PF_Broadcast_WriteChar ;
pr_builtin [ 61 ] = PF_Broadcast_WriteShort ;
pr_builtin [ 62 ] = PF_Broadcast_WriteLong ;
pr_builtin [ 63 ] = PF_Broadcast_WriteCoord ;
pr_builtin [ 64 ] = PF_Broadcast_WriteAngle ;
pr_builtin [ 65 ] = PF_Broadcast_WriteString ;
pr_builtin [ 66 ] = PF_Broadcast_WriteEntity ;
}
2004-08-31 23:58:18 +00:00
if ( ! pr_compatabilitytest . value )
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
builtincount [ BuiltinList [ i ] . ebfsnum ] + + ;
}
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
{
if ( BuiltinList [ i ] . ebfsnum )
{
if ( pr_builtin [ BuiltinList [ i ] . ebfsnum ] = = PF_Fixme & & builtincount [ BuiltinList [ i ] . ebfsnum ] = = 1 )
{
pr_builtin [ BuiltinList [ i ] . ebfsnum ] = BuiltinList [ i ] . bifunc ;
Con_DPrintf ( " Enabled %s \n " , BuiltinList [ i ] . name ) ;
}
else if ( pr_builtin [ i ] ! = BuiltinList [ i ] . bifunc )
Con_DPrintf ( " Not enabled %s \n " , BuiltinList [ i ] . name ) ;
}
}
2004-08-23 00:15:46 +00:00
}
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
char * builtinmap ;
int binum ;
builtinmap = COM_LoadTempFile ( " fte_bimap.txt " ) ;
while ( 1 )
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
builtinmap = COM_Parse ( builtinmap ) ;
if ( ! builtinmap )
break ;
binum = atoi ( com_token ) ;
builtinmap = COM_Parse ( builtinmap ) ;
for ( i = 0 ; BuiltinList [ i ] . name ; i + + )
2004-08-23 00:15:46 +00:00
{
2004-08-31 23:58:18 +00:00
if ( ! strcmp ( BuiltinList [ i ] . name , com_token ) )
{
pr_builtin [ binum ] = BuiltinList [ i ] . bifunc ;
break ;
}
2004-08-23 00:15:46 +00:00
}
2004-08-31 23:58:18 +00:00
if ( ! BuiltinList [ i ] . name )
2004-09-13 02:22:02 +00:00
Con_Printf ( " Failed to map builtin %s to %i specified in fte_bimap.dat \n " , com_token , binum ) ;
2004-08-23 00:15:46 +00:00
}
}
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < sizeof ( QSG_Extensions ) / sizeof ( QSG_Extensions [ 0 ] ) ; i + + )
{
if ( QSG_Extensions [ i ] . enabled )
* QSG_Extensions [ i ] . enabled = false ;
}
if ( type = = PROG_QW & & pr_imitatemvdsv . value > 0 ) //pretend to be mvdsv for a bit.
{
2004-10-19 16:10:14 +00:00
if ( PR_EnableEBFSBuiltin ( " teamfield " , 87 ) ! = 87 | |
PR_EnableEBFSBuiltin ( " substr " , 88 ) ! = 88 | |
PR_EnableEBFSBuiltin ( " mvdstrcat " , 89 ) ! = 89 | |
PR_EnableEBFSBuiltin ( " mvdstrlen " , 90 ) ! = 90 | |
PR_EnableEBFSBuiltin ( " str2byte " , 91 ) ! = 91 | |
PR_EnableEBFSBuiltin ( " str2short " , 92 ) ! = 92 | |
PR_EnableEBFSBuiltin ( " mvdnewstr " , 93 ) ! = 93 | |
PR_EnableEBFSBuiltin ( " mvdfreestr " , 94 ) ! = 94 | |
PR_EnableEBFSBuiltin ( " conprint " , 95 ) ! = 95 | |
PR_EnableEBFSBuiltin ( " readcmd " , 96 ) ! = 96 | |
PR_EnableEBFSBuiltin ( " mvdstrcpy " , 97 ) ! = 97 | |
PR_EnableEBFSBuiltin ( " strstr " , 98 ) ! = 98 | |
PR_EnableEBFSBuiltin ( " mvdstrncpy " , 99 ) ! = 99 | |
PR_EnableEBFSBuiltin ( " log " , 100 ) ! = 100 | |
// PR_EnableEBFSBuiltin("redirectcmd", 101)!= 101 ||
2004-11-17 17:52:18 +00:00
PR_EnableEBFSBuiltin ( " mvdcalltimeofday " , 102 ) ! = 102 | |
2004-10-19 16:10:14 +00:00
PR_EnableEBFSBuiltin ( " forcedemoframe " , 103 ) ! = 103 )
2004-09-13 02:22:02 +00:00
Con_Printf ( " Failed to register all MVDSV builtins \n " ) ;
2004-10-10 06:32:29 +00:00
else
Con_Printf ( " Be aware that MVDSV does not follow standards. Please encourage your mod developers to not require pr_imitatemvdsv to be set. \n " ) ;
2004-08-23 00:15:46 +00:00
}
}
builtin_t * pr_builtins = pr_builtin ;
int pr_numbuiltins = sizeof ( pr_builtin ) / sizeof ( pr_builtin [ 0 ] ) ;
void PR_RegisterSVBuiltins ( void )
2004-09-04 17:52:32 +00:00
{ /*
2004-08-23 00:15:46 +00:00
PR_RegisterBuiltin ( svprogfuncs , " getmodelindex " , & PF_WeapIndex ) ;
PR_RegisterBuiltin ( svprogfuncs , " tracebox " , & PF_traceline ) ;
# ifdef Q2BSPS
PR_RegisterBuiltin ( svprogfuncs , " SetAreaPortalState " , & PF_OpenPortal ) ;
# endif
PR_RegisterBuiltin ( svprogfuncs , " logtext " , & PF_logstring ) ;
PR_RegisterBuiltin ( svprogfuncs , " newstring " , & PF_newstring ) ;
PR_RegisterBuiltin ( svprogfuncs , " forgetstring " , & PF_forgetstring ) ;
PR_RegisterBuiltin ( svprogfuncs , " strlen " , & PF_strlen ) ;
PR_RegisterBuiltin ( svprogfuncs , " strcat " , & PF_strcat ) ;
PR_RegisterBuiltin ( svprogfuncs , " strcatp " , & PF_strcatp ) ;
PR_RegisterBuiltin ( svprogfuncs , " ftosp " , & PF_ftosp ) ;
PR_RegisterBuiltin ( svprogfuncs , " redstring " , & PF_redstring ) ;
# ifdef USEBULLETENS
PR_RegisterBuiltin ( svprogfuncs , " bulleten " , & PF_bulleten ) ;
# endif
# ifdef SVCHAT
PR_RegisterBuiltin ( svprogfuncs , " chat " , & PF_chat ) ;
# endif
PR_RegisterBuiltin ( svprogfuncs , " cvar_string " , & PF_cvar_string ) ;
PR_RegisterBuiltin ( svprogfuncs , " _externcall " , & PF_externcall ) ;
PR_RegisterBuiltin ( svprogfuncs , " _addprogs " , & PF_addprogs ) ;
PR_RegisterBuiltin ( svprogfuncs , " _externvalue " , & PF_externvalue ) ;
PR_RegisterBuiltin ( svprogfuncs , " _externset " , & PF_externset ) ;
// PR_RegisterBuiltin(svprogfuncs, "_externrefcall", &PF_externrefcall);
PR_RegisterBuiltin ( svprogfuncs , " instr " , & PF_instr ) ;
PR_RegisterBuiltin ( svprogfuncs , " temppointentity " , & PF_tempentity ) ;
//these are for nq progs
PR_RegisterBuiltin ( svprogfuncs , " logfrag " , & PF_logfrag ) ;
PR_RegisterBuiltin ( svprogfuncs , " infokey " , & PF_infokey ) ;
2004-09-04 17:52:32 +00:00
PR_RegisterBuiltin ( svprogfuncs , " stof " , & PF_stof ) ; */
2004-08-23 00:15:46 +00:00
}
void PR_RegisterFields ( void ) //it's just easier to do it this way.
{
2005-03-28 00:11:59 +00:00
# define fieldfloat(name) PR_RegisterFieldVar(svprogfuncs, ev_float, #name, (int)&((entvars_t*)0)->name, -1)
# define fieldvector(name) PR_RegisterFieldVar(svprogfuncs, ev_vector, #name, (int)&((entvars_t*)0)->name, -1)
# define fieldentity(name) PR_RegisterFieldVar(svprogfuncs, ev_entity, #name, (int)&((entvars_t*)0)->name, -1)
# define fieldstring(name) PR_RegisterFieldVar(svprogfuncs, ev_string, #name, (int)&((entvars_t*)0)->name, -1)
# define fieldfunction(name) PR_RegisterFieldVar(svprogfuncs, ev_function, #name, (int)&((entvars_t*)0)->name, -1)
2004-08-23 00:15:46 +00:00
fieldfloat ( modelindex ) ;
fieldvector ( absmin ) ;
fieldvector ( absmax ) ;
fieldfloat ( ltime ) ;
fieldfloat ( lastruntime ) ;
fieldfloat ( movetype ) ;
fieldfloat ( solid ) ;
fieldvector ( origin ) ;
fieldvector ( oldorigin ) ;
fieldvector ( velocity ) ;
fieldvector ( angles ) ;
fieldvector ( avelocity ) ;
fieldstring ( classname ) ;
fieldstring ( model ) ;
fieldfloat ( frame ) ;
fieldfloat ( skin ) ;
fieldfloat ( effects ) ;
fieldvector ( mins ) ;
fieldvector ( maxs ) ;
fieldvector ( size ) ;
fieldfunction ( touch ) ;
fieldfunction ( use ) ;
fieldfunction ( think ) ;
fieldfunction ( blocked ) ;
fieldfloat ( nextthink ) ;
fieldentity ( groundentity ) ;
fieldfloat ( health ) ;
fieldfloat ( frags ) ;
fieldfloat ( weapon ) ;
fieldstring ( weaponmodel ) ;
fieldfloat ( weaponframe ) ;
fieldfloat ( currentammo ) ;
fieldfloat ( ammo_shells ) ;
fieldfloat ( ammo_nails ) ;
fieldfloat ( ammo_rockets ) ;
fieldfloat ( ammo_cells ) ;
fieldfloat ( items ) ;
fieldfloat ( takedamage ) ;
fieldentity ( chain ) ;
fieldfloat ( deadflag ) ;
fieldvector ( view_ofs ) ;
fieldfloat ( button0 ) ;
fieldfloat ( button1 ) ;
fieldfloat ( button2 ) ;
2004-09-04 17:52:32 +00:00
fieldfloat ( button3 ) ;
fieldfloat ( button4 ) ;
fieldfloat ( button5 ) ;
fieldfloat ( button6 ) ;
fieldfloat ( button7 ) ;
fieldfloat ( button8 ) ;
2004-08-23 00:15:46 +00:00
fieldfloat ( impulse ) ;
fieldfloat ( fixangle ) ;
fieldvector ( v_angle ) ;
fieldstring ( netname ) ;
fieldentity ( enemy ) ;
fieldfloat ( flags ) ;
fieldfloat ( colormap ) ;
fieldfloat ( team ) ;
fieldfloat ( max_health ) ;
fieldfloat ( teleport_time ) ;
fieldfloat ( armortype ) ;
fieldfloat ( armorvalue ) ;
fieldfloat ( waterlevel ) ;
fieldfloat ( watertype ) ;
fieldfloat ( ideal_yaw ) ;
fieldfloat ( yaw_speed ) ;
fieldentity ( aiment ) ;
fieldentity ( goalentity ) ;
fieldfloat ( spawnflags ) ;
fieldstring ( target ) ;
fieldstring ( targetname ) ;
fieldfloat ( dmg_take ) ;
fieldfloat ( dmg_save ) ;
fieldentity ( dmg_inflictor ) ;
fieldentity ( owner ) ;
fieldvector ( movedir ) ;
fieldfloat ( sounds ) ;
fieldstring ( noise ) ;
fieldstring ( noise1 ) ;
fieldstring ( noise2 ) ;
fieldstring ( noise3 ) ;
//the rest are extras. (not in header)
fieldfloat ( gravity ) ; //standard extension
fieldfloat ( maxspeed ) ; //standard extension
fieldfloat ( items2 ) ; //standard nq
2004-10-10 06:32:29 +00:00
fieldvector ( punchangle ) ; //standard nq
2004-08-23 00:15:46 +00:00
fieldfloat ( scale ) ;
//fieldfloat(transparency);
fieldfloat ( alpha ) ;
fieldfloat ( fatness ) ;
fieldentity ( view2 ) ;
fieldvector ( movement ) ;
2005-03-28 00:11:59 +00:00
PR_RegisterFieldVar ( svprogfuncs , ev_float , " buttonforward " , ( int ) & ( ( entvars_t * ) 0 ) - > movement [ 0 ] , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " buttonright " , ( int ) & ( ( entvars_t * ) 0 ) - > movement [ 1 ] , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " buttonup " , ( int ) & ( ( entvars_t * ) 0 ) - > movement [ 2 ] , - 1 ) ;
2004-08-23 00:15:46 +00:00
fieldfloat ( fteflags ) ;
fieldfloat ( vweapmodelindex ) ;
//dp extra fields
fieldentity ( nodrawtoclient ) ;
fieldentity ( drawonlytoclient ) ;
2005-05-15 18:49:04 +00:00
fieldentity ( viewmodelforclient ) ;
fieldentity ( exteriormodeltoclient ) ;
2004-08-23 00:15:46 +00:00
2005-05-19 02:53:03 +00:00
fieldfloat ( glow_size ) ;
fieldfloat ( glow_color ) ;
fieldfloat ( glow_trail ) ;
2005-05-17 02:36:54 +00:00
2004-08-23 00:15:46 +00:00
//UDC_EXTEFFECT... yuckie
2005-03-28 00:11:59 +00:00
PR_RegisterFieldVar ( svprogfuncs , ev_float , " fieldcolor " , ( int ) & ( ( entvars_t * ) 0 ) - > seefcolour , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " fieldsizex " , ( int ) & ( ( entvars_t * ) 0 ) - > seefsizex , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " fieldsizey " , ( int ) & ( ( entvars_t * ) 0 ) - > seefsizey , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " fieldsizez " , ( int ) & ( ( entvars_t * ) 0 ) - > seefsizez , - 1 ) ;
PR_RegisterFieldVar ( svprogfuncs , ev_float , " fieldoffset " , ( int ) & ( ( entvars_t * ) 0 ) - > seefoffset , - 1 ) ;
2004-08-23 00:15:46 +00:00
//hexen 2 stuff
fieldfloat ( playerclass ) ;
fieldfloat ( hull ) ;
2004-10-10 06:32:29 +00:00
fieldfloat ( hasted ) ;
2004-08-23 00:15:46 +00:00
fieldfloat ( light_level ) ;
fieldfloat ( abslight ) ;
fieldfloat ( drawflags ) ;
fieldentity ( movechain ) ;
fieldfunction ( chainmoved ) ;
2004-08-31 23:58:18 +00:00
//QSG_DIMENSION_PLANES
2004-09-04 17:52:32 +00:00
fieldfloat ( dimension_see ) ;
fieldfloat ( dimension_seen ) ;
2004-08-31 23:58:18 +00:00
fieldfloat ( dimension_ghost ) ;
2004-09-04 17:52:32 +00:00
fieldfloat ( dimension_ghost_alpha ) ;
fieldfloat ( dimension_solid ) ;
fieldfloat ( dimension_hit ) ;
2004-08-31 23:58:18 +00:00
2005-02-28 07:16:19 +00:00
fieldfunction ( SendEntity ) ;
fieldfloat ( Version ) ;
//Tell the qc library to split the entity fields each side.
//the fields above become < 0, the remaining fields specified by the qc stay where the mod specified, as far as possible (with addons at least).
//this means that custom array offsets still work in mods like ktpro.
2004-08-23 00:15:46 +00:00
if ( pr_fixbrokenqccarrays . value )
2005-02-12 18:56:04 +00:00
PR_RegisterFieldVar ( svprogfuncs , 0 , NULL , 0 , 0 ) ;
2004-08-23 00:15:46 +00:00
}
2004-11-29 01:21:00 +00:00
# endif