2 // Basically every vm builtin cmd should be in here.
3 // All 3 builtin and extension lists can be found here
4 // cause large (I think they will) parts are from pr_cmds the same copyright like in pr_cmds
9 ============================================================================
13 checkextension(string)
18 sprint(float clientnum,...[string])
19 centerprint(...[string])
20 vector normalize(vector)
22 float vectoyaw(vector)
23 vector vectoangles(vector)
27 cvar_set (string,string)
33 float stof(...[string])
36 entity find(entity start, .string field, string match)
38 entity findfloat(entity start, .float field, float match)
39 entity findentity(entity start, .entity field, entity match)
41 entity findchain(.string field, string match)
43 entity findchainfloat(.string field, float match)
44 entity findchainentity(.string field, entity match)
46 string precache_file(string)
47 string precache_sound (string sample)
55 entity nextent(entity)
60 float registercvar (string name, string value, float flags)
61 float min(float a, float b, ...[float])
62 float max(float a, float b, ...[float])
63 float bound(float min, float value, float max)
64 float pow(float a, float b)
65 copyentity(entity src, entity dst)
66 float fopen(string filename, float mode)
68 string fgets(float fhandle)
69 fputs(float fhandle, string s)
70 float strlen(string s)
71 string strcat(string,string,...[string])
72 string substring(string s, float start, float length)
74 string strzone(string s)
76 float tokenize(string s)
81 clientcommand(float client, string s) (for client and menu)
82 changelevel(string map)
83 localsound(string sample)
86 loadfromdata(string data)
87 loadfromfile(string file)
88 float mod(float val, float m)
89 const string str_cvar (string)
93 float search_begin(string pattern, float caseinsensitive, float quiet)
94 void search_end(float handle)
95 float search_getsize(float handle)
96 string search_getfilename(float handle, float num)
98 string chr(float ascii)
100 perhaps only : Menu : WriteMsg
101 ===============================
103 WriteByte(float data, float dest, float desto)
104 WriteChar(float data, float dest, float desto)
105 WriteShort(float data, float dest, float desto)
106 WriteLong(float data, float dest, float desto)
107 WriteAngle(float data, float dest, float desto)
108 WriteCoord(float data, float dest, float desto)
109 WriteString(string data, float dest, float desto)
110 WriteEntity(entity data, float dest, float desto)
112 Client & Menu : draw functions
113 ===============================
115 float iscachedpic(string pic)
116 string precache_pic(string pic)
118 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
119 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
120 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
121 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
122 drawsetcliparea(float x, float y, float width, float height)
124 vector getimagesize(string pic)
127 ==============================================================================
131 setkeydest(float dest)
133 setmousetarget(float target)
134 float getmousetarget(void)
136 callfunction(...,string function_name)
137 writetofile(float fhandle, entity ent)
138 float isfunction(string function_name)
139 vector getresolution(float number)
140 string keynumtostring(float keynum)
141 string findkeysforcommand(string command)
142 float gethostcachevalue(float type)
143 string gethostcachestring(float type, float hostnr)
148 #include "quakedef.h"
149 #include "progdefs.h"
150 #include "clprogdefs.h"
151 #include "mprogdefs.h"
153 //============================================================================
154 // nice helper macros
156 #ifndef VM_NOPARMCHECK
157 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
159 #define VM_SAFEPARMCOUNT(p,f)
162 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
164 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
166 #define e10 0,0,0,0,0,0,0,0,0,0
167 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
168 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
170 //============================================================================
173 // string zone mempool
174 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
176 // temp string handling
177 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
178 #define VM_STRINGTEMP_BUFFERS 16
179 #define VM_STRINGTEMP_LENGTH 4096
180 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
181 static int vm_string_tempindex = 0;
184 #define MAX_QC_CVARS 128 * PRVM_MAXPROGS
185 cvar_t vm_qc_cvar[MAX_QC_CVARS];
186 int vm_currentqc_cvar;
189 #define MAX_VMFILES 256
190 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
191 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
193 qfile_t *vm_files[MAX_PRVMFILES];
195 // qc fs search handling
196 #define MAX_VMSEARCHES 128
197 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
198 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
200 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
202 static char *VM_GetTempString(void)
205 s = vm_string_temp[vm_string_tempindex];
206 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
210 void VM_CheckEmptyString (char *s)
213 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
216 //============================================================================
219 void VM_VarString(int first, char *out, int outlength)
225 outend = out + outlength - 1;
226 for (i = first;i < prog->argc && out < outend;i++)
228 s = PRVM_G_STRING((OFS_PARM0+i*3));
229 while (out < outend && *s)
239 returns true if the extension is supported by the server
241 checkextension(extensionname)
245 // kind of helper function
246 static qboolean checkextension(char *name)
252 for (e = prog->extensionstring;*e;e++)
259 while (*e && *e != ' ')
261 if (e - start == len)
262 if (!strncasecmp(start, name, len))
270 void VM_checkextension (void)
272 VM_SAFEPARMCOUNT(1,VM_checkextension);
274 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
281 This is a TERMINAL error, which will kill off the entire prog.
290 char string[VM_STRINGTEMP_LENGTH];
292 VM_VarString(0, string, sizeof(string));
293 Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
296 ed = PRVM_G_EDICT(prog->self->ofs);
300 PRVM_ERROR ("%s: Program error", PRVM_NAME);
307 Dumps out self, then an error message. The program is aborted and self is
308 removed, but the level can continue.
313 void VM_objerror (void)
316 char string[VM_STRINGTEMP_LENGTH];
318 VM_VarString(0, string, sizeof(string));
319 Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
322 ed = PRVM_G_EDICT (prog->self->ofs);
328 // objerror has to display the object fields -> else call
329 PRVM_ERROR ("VM_objecterror: self not defined !\n");
334 VM_print (actually used only by client and menu)
343 char string[VM_STRINGTEMP_LENGTH];
345 VM_VarString(0, string, sizeof(string));
353 broadcast print to everyone on server
358 void VM_bprint (void)
360 char string[VM_STRINGTEMP_LENGTH];
364 Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
368 VM_VarString(0, string, sizeof(string));
369 SV_BroadcastPrintf("%s", string);
374 VM_sprint (menu & client but only if server.active == true)
376 single print to a specific client
378 sprint(float clientnum,...[string])
381 void VM_sprint (void)
385 char string[VM_STRINGTEMP_LENGTH];
387 //find client for this entity
388 clientnum = PRVM_G_FLOAT(OFS_PARM0);
389 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
391 Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
395 client = svs.clients + clientnum;
396 if (!client->netconnection)
398 VM_VarString(1, string, sizeof(string));
399 MSG_WriteChar(&client->message,svc_print);
400 MSG_WriteString(&client->message, string);
407 single print to the screen
409 centerprint(clientent, value)
412 void VM_centerprint (void)
414 char string[VM_STRINGTEMP_LENGTH];
416 VM_VarString(0, string, sizeof(string));
417 SCR_CenterPrint(string);
424 vector normalize(vector)
427 void VM_normalize (void)
433 VM_SAFEPARMCOUNT(1,VM_normalize);
435 value1 = PRVM_G_VECTOR(OFS_PARM0);
437 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
441 newvalue[0] = newvalue[1] = newvalue[2] = 0;
445 newvalue[0] = value1[0] * new;
446 newvalue[1] = value1[1] * new;
447 newvalue[2] = value1[2] * new;
450 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
465 VM_SAFEPARMCOUNT(1,VM_vlen);
467 value1 = PRVM_G_VECTOR(OFS_PARM0);
469 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
472 PRVM_G_FLOAT(OFS_RETURN) = new;
479 float vectoyaw(vector)
482 void VM_vectoyaw (void)
487 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
489 value1 = PRVM_G_VECTOR(OFS_PARM0);
491 if (value1[1] == 0 && value1[0] == 0)
495 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
500 PRVM_G_FLOAT(OFS_RETURN) = yaw;
508 vector vectoangles(vector)
511 void VM_vectoangles (void)
517 VM_SAFEPARMCOUNT(1,VM_vectoangles);
519 value1 = PRVM_G_VECTOR(OFS_PARM0);
521 if (value1[1] == 0 && value1[0] == 0)
531 // LordHavoc: optimized a bit
534 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
538 else if (value1[1] > 0)
543 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
544 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
549 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
550 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
551 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
558 Returns a number from 0<= num < 1
563 void VM_random (void)
567 VM_SAFEPARMCOUNT(0,VM_random);
569 num = (rand ()&0x7fff) / ((float)0x7fff);
571 PRVM_G_FLOAT(OFS_RETURN) = num;
578 Each entity can have eight independant sound sources, like voice,
581 Channel 0 is an auto-allocate channel, the others override anything
582 already running on that entity/channel pair.
584 An attenuation of 0 will play full volume everywhere in the level.
585 Larger attenuations will drop off.
598 entity = G_EDICT(OFS_PARM0);
599 channel = G_FLOAT(OFS_PARM1);
600 sample = G_STRING(OFS_PARM2);
601 volume = G_FLOAT(OFS_PARM3) * 255;
602 attenuation = G_FLOAT(OFS_PARM4);
604 if (volume < 0 || volume > 255)
605 Host_Error ("SV_StartSound: volume = %i", volume);
607 if (attenuation < 0 || attenuation > 4)
608 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
610 if (channel < 0 || channel > 7)
611 Host_Error ("SV_StartSound: channel = %i", channel);
613 SV_StartSound (entity, channel, sample, volume, attenuation);
621 localsound(string sample)
624 void VM_localsound(void)
628 VM_SAFEPARMCOUNT(1,VM_localsound);
630 s = PRVM_G_STRING(OFS_PARM0);
634 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
635 PRVM_G_FLOAT(OFS_RETURN) = -4;
640 PRVM_G_FLOAT(OFS_RETURN) = 1;
652 PRVM_ERROR ("%s: break statement", PRVM_NAME);
655 //============================================================================
661 Sends text over to the client's execution buffer
663 [localcmd (string) or]
667 void VM_localcmd (void)
669 VM_SAFEPARMCOUNT(1,VM_localcmd);
671 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
683 VM_SAFEPARMCOUNT(1,VM_cvar);
685 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
692 const string str_cvar (string)
695 void VM_str_cvar(void)
698 const char *cvar_string;
699 VM_SAFEPARMCOUNT(1,VM_str_cvar);
701 name = PRVM_G_STRING(OFS_PARM0);
704 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
706 VM_CheckEmptyString(name);
708 out = VM_GetTempString();
710 cvar_string = Cvar_VariableString(name);
712 strcpy(out, cvar_string);
714 PRVM_G_INT(OFS_PARM0) = PRVM_SetString(out);
721 void cvar_set (string,string)
724 void VM_cvar_set (void)
726 VM_SAFEPARMCOUNT(2,VM_cvar_set);
728 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
738 void VM_dprint (void)
740 char string[VM_STRINGTEMP_LENGTH];
741 if (developer.integer)
743 VM_VarString(0, string, sizeof(string));
744 Con_Printf("%s: %s", PRVM_NAME, string);
761 VM_SAFEPARMCOUNT(1, VM_ftos);
763 v = PRVM_G_FLOAT(OFS_PARM0);
765 s = VM_GetTempString();
766 if ((float)((int)v) == v)
767 sprintf(s, "%i", (int)v);
770 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
785 VM_SAFEPARMCOUNT(1,VM_fabs);
787 v = PRVM_G_FLOAT(OFS_PARM0);
788 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
803 VM_SAFEPARMCOUNT(1,VM_vtos);
805 s = VM_GetTempString();
806 sprintf (s, "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
807 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
822 VM_SAFEPARMCOUNT(1, VM_etos);
824 s = VM_GetTempString();
825 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
826 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
833 float stof(...[string])
838 char string[VM_STRINGTEMP_LENGTH];
839 VM_VarString(0, string, sizeof(string));
840 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
854 prog->xfunction->builtinsprofile += 20;
855 ed = PRVM_ED_Alloc();
867 void VM_remove (void)
870 prog->xfunction->builtinsprofile += 20;
872 VM_SAFEPARMCOUNT(1, VM_remove);
874 ed = PRVM_G_EDICT(OFS_PARM0);
875 // if (ed == prog->edicts)
876 // PRVM_ERROR ("remove: tried to remove world\n");
877 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
878 // Host_Error("remove: tried to remove a client\n");
886 entity find(entity start, .string field, string match)
897 VM_SAFEPARMCOUNT(3,VM_find);
899 e = PRVM_G_EDICTNUM(OFS_PARM0);
900 f = PRVM_G_INT(OFS_PARM1);
901 s = PRVM_G_STRING(OFS_PARM2);
905 // return reserved edict 0 (could be used for whatever the prog wants)
906 VM_RETURN_EDICT(prog->edicts);
910 for (e++ ; e < prog->num_edicts ; e++)
912 prog->xfunction->builtinsprofile++;
913 ed = PRVM_EDICT_NUM(e);
916 t = PRVM_E_STRING(ed,f);
926 VM_RETURN_EDICT(prog->edicts);
933 entity findfloat(entity start, .float field, float match)
934 entity findentity(entity start, .entity field, entity match)
937 // LordHavoc: added this for searching float, int, and entity reference fields
938 void VM_findfloat (void)
945 VM_SAFEPARMCOUNT(3,VM_findfloat);
947 e = PRVM_G_EDICTNUM(OFS_PARM0);
948 f = PRVM_G_INT(OFS_PARM1);
949 s = PRVM_G_FLOAT(OFS_PARM2);
951 for (e++ ; e < prog->num_edicts ; e++)
953 prog->xfunction->builtinsprofile++;
954 ed = PRVM_EDICT_NUM(e);
957 if (PRVM_E_FLOAT(ed,f) == s)
964 VM_RETURN_EDICT(prog->edicts);
971 entity findchain(.string field, string match)
974 int PRVM_ED_FindFieldOffset(const char *field);
975 // chained search for strings in entity fields
976 // entity(.string field, string match) findchain = #402;
977 void VM_findchain (void)
983 prvm_edict_t *ent, *chain;
985 VM_SAFEPARMCOUNT(2,VM_findchain);
987 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
988 if(!prog->flag & PRVM_FE_CHAIN)
989 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
991 chain_of = PRVM_ED_FindFieldOffset ("chain");
993 chain = prog->edicts;
995 f = PRVM_G_INT(OFS_PARM0);
996 s = PRVM_G_STRING(OFS_PARM1);
999 VM_RETURN_EDICT(prog->edicts);
1003 ent = PRVM_NEXT_EDICT(prog->edicts);
1004 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1006 prog->xfunction->builtinsprofile++;
1009 t = PRVM_E_STRING(ent,f);
1015 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1019 VM_RETURN_EDICT(chain);
1026 entity findchainfloat(.string field, float match)
1027 entity findchainentity(.string field, entity match)
1030 // LordHavoc: chained search for float, int, and entity reference fields
1031 // entity(.string field, float match) findchainfloat = #403;
1032 void VM_findchainfloat (void)
1038 prvm_edict_t *ent, *chain;
1040 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1042 if(!prog->flag & PRVM_FE_CHAIN)
1043 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1045 chain_of = PRVM_ED_FindFieldOffset ("chain");
1047 chain = (prvm_edict_t *)prog->edicts;
1049 f = PRVM_G_INT(OFS_PARM0);
1050 s = PRVM_G_FLOAT(OFS_PARM1);
1052 ent = PRVM_NEXT_EDICT(prog->edicts);
1053 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1055 prog->xfunction->builtinsprofile++;
1058 if (E_FLOAT(ent,f) != s)
1061 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1065 VM_RETURN_EDICT(chain);
1072 string precache_file(string)
1075 void VM_precache_file (void)
1076 { // precache_file is only used to copy files with qcc, it does nothing
1077 VM_SAFEPARMCOUNT(1,VM_precache_file);
1079 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1086 used instead of the other VM_precache_* functions in the builtin list
1090 void VM_precache_error (void)
1092 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1099 string precache_sound (string sample)
1102 void VM_precache_sound (void)
1106 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1108 s = PRVM_G_STRING(OFS_PARM0);
1109 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1110 VM_CheckEmptyString (s);
1114 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1118 if(!S_PrecacheSound(s,true))
1119 Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1129 void VM_coredump (void)
1131 VM_SAFEPARMCOUNT(0,VM_coredump);
1133 Cbuf_AddText("prvm_edicts ");
1134 Cbuf_AddText(PRVM_NAME);
1145 void PRVM_StackTrace(void);
1146 void VM_stackdump (void)
1148 VM_SAFEPARMCOUNT(0, VM_stackdump);
1163 VM_SAFEPARMCOUNT(0, VM_crash);
1165 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1175 void VM_traceon (void)
1177 VM_SAFEPARMCOUNT(0,VM_traceon);
1189 void VM_traceoff (void)
1191 VM_SAFEPARMCOUNT(0,VM_traceoff);
1193 prog->trace = false;
1203 void VM_eprint (void)
1205 VM_SAFEPARMCOUNT(1,VM_eprint);
1207 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1221 VM_SAFEPARMCOUNT(1,VM_rint);
1223 f = PRVM_G_FLOAT(OFS_PARM0);
1225 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1227 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1237 void VM_floor (void)
1239 VM_SAFEPARMCOUNT(1,VM_floor);
1241 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1253 VM_SAFEPARMCOUNT(1,VM_ceil);
1255 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1263 entity nextent(entity)
1266 void VM_nextent (void)
1271 i = PRVM_G_EDICTNUM(OFS_PARM0);
1274 prog->xfunction->builtinsprofile++;
1276 if (i == prog->num_edicts)
1278 VM_RETURN_EDICT(prog->edicts);
1281 ent = PRVM_EDICT_NUM(i);
1284 VM_RETURN_EDICT(ent);
1291 ===============================================================================
1294 used only for client and menu
1295 severs uses VM_SV_...
1297 Write*(* data, float type, float to)
1299 ===============================================================================
1302 #define MSG_BROADCAST 0 // unreliable to all
1303 #define MSG_ONE 1 // reliable to one (msg_entity)
1304 #define MSG_ALL 2 // reliable to all
1305 #define MSG_INIT 3 // write to the init string
1307 sizebuf_t *VM_WriteDest (void)
1313 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1315 dest = G_FLOAT(OFS_PARM1);
1319 return &sv.datagram;
1322 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1323 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1324 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1326 return &svs.clients[destclient].message;
1329 return &sv.reliable_datagram;
1335 PRVM_ERROR ("WriteDest: bad destination");
1342 void VM_WriteByte (void)
1344 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1347 void VM_WriteChar (void)
1349 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1352 void VM_WriteShort (void)
1354 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1357 void VM_WriteLong (void)
1359 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1362 void VM_WriteAngle (void)
1364 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1367 void VM_WriteCoord (void)
1369 MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1372 void VM_WriteString (void)
1374 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1377 void VM_WriteEntity (void)
1379 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1382 //=============================================================================
1389 changelevel(string map)
1392 void VM_changelevel (void)
1396 VM_SAFEPARMCOUNT(1, VM_changelevel);
1400 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1404 // make sure we don't issue two changelevels
1405 if (svs.changelevel_issued)
1407 svs.changelevel_issued = true;
1409 s = G_STRING(OFS_PARM0);
1410 Cbuf_AddText (va("changelevel %s\n",s));
1422 VM_SAFEPARMCOUNT(1,VM_sin);
1423 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1434 VM_SAFEPARMCOUNT(1,VM_cos);
1435 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1447 VM_SAFEPARMCOUNT(1,VM_sqrt);
1448 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1455 Returns a vector of length < 1 and > 0
1460 void VM_randomvec (void)
1465 VM_SAFEPARMCOUNT(0, VM_randomvec);
1470 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1471 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1472 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1474 while (DotProduct(temp, temp) >= 1);
1475 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1478 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1479 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1480 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1481 // length returned always > 0
1482 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1483 VectorScale(temp,length, temp);*/
1484 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1487 //=============================================================================
1493 float registercvar (string name, string value, float flags)
1496 void VM_registercvar (void)
1502 VM_SAFEPARMCOUNT(3,VM_registercvar);
1504 name = PRVM_G_STRING(OFS_PARM0);
1505 value = PRVM_G_STRING(OFS_PARM1);
1506 flags = PRVM_G_FLOAT(OFS_PARM2);
1507 PRVM_G_FLOAT(OFS_RETURN) = 0;
1509 if(flags > CVAR_MAXFLAGSVAL)
1512 // first check to see if it has already been defined
1513 if (Cvar_FindVar (name))
1516 // check for overlap with a command
1517 if (Cmd_Exists (name))
1519 Con_Printf ("VM_registercvar: %s is a command\n", name);
1523 if (vm_currentqc_cvar >= MAX_QC_CVARS)
1524 PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1526 // copy the name and value
1527 variable = &vm_qc_cvar[vm_currentqc_cvar++];
1528 variable->flags = flags;
1529 variable->name = Z_Malloc (strlen(name)+1);
1530 strcpy (variable->name, name);
1531 variable->string = Z_Malloc (strlen(value)+1);
1532 strcpy (variable->string, value);
1533 variable->value = atof (value);
1535 Cvar_RegisterVariable(variable);
1536 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1543 returns the minimum of two supplied floats
1545 float min(float a, float b, ...[float])
1550 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1551 if (prog->argc == 2)
1552 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1553 else if (prog->argc >= 3)
1556 float f = PRVM_G_FLOAT(OFS_PARM0);
1557 for (i = 1;i < prog->argc;i++)
1558 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1559 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1560 PRVM_G_FLOAT(OFS_RETURN) = f;
1563 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1570 returns the maximum of two supplied floats
1572 float max(float a, float b, ...[float])
1577 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1578 if (prog->argc == 2)
1579 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1580 else if (prog->argc >= 3)
1583 float f = PRVM_G_FLOAT(OFS_PARM0);
1584 for (i = 1;i < prog->argc;i++)
1585 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1586 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1587 G_FLOAT(OFS_RETURN) = f;
1590 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1597 returns number bounded by supplied range
1599 float bound(float min, float value, float max)
1602 void VM_bound (void)
1604 VM_SAFEPARMCOUNT(3,VM_bound);
1605 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1612 returns a raised to power b
1614 float pow(float a, float b)
1619 VM_SAFEPARMCOUNT(2,VM_pow);
1620 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1627 copies data from one entity to another
1629 copyentity(entity src, entity dst)
1632 void VM_copyentity (void)
1634 prvm_edict_t *in, *out;
1635 VM_SAFEPARMCOUNT(2,VM_copyentity);
1636 in = PRVM_G_EDICT(OFS_PARM0);
1637 out = PRVM_G_EDICT(OFS_PARM1);
1638 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1645 sets the color of a client and broadcasts the update to all connected clients
1647 setcolor(clientent, value)
1650 /*void PF_setcolor (void)
1656 entnum = G_EDICTNUM(OFS_PARM0);
1657 i = G_FLOAT(OFS_PARM1);
1659 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1661 Con_Printf ("tried to setcolor a non-client\n");
1665 client = svs.clients + entnum-1;
1666 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1669 client->old_colors = i;
1670 client->edict->v->team = (i & 15) + 1;
1672 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1673 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1674 MSG_WriteByte (&sv.reliable_datagram, i);
1677 void VM_Files_Init(void)
1679 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1682 void VM_Files_CloseAll(void)
1685 for (i = 0;i < MAX_VMFILES;i++)
1688 FS_Close(VM_FILES[i]);
1689 //VM_FILES[i] = NULL;
1691 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1698 float fopen(string filename, float mode)
1701 // float(string filename, float mode) fopen = #110;
1702 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1703 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1707 char *modestring, *filename;
1709 VM_SAFEPARMCOUNT(2,VM_fopen);
1711 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1712 if (VM_FILES[filenum] == NULL)
1714 if (filenum >= MAX_VMFILES)
1716 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1717 PRVM_G_FLOAT(OFS_RETURN) = -2;
1720 mode = PRVM_G_FLOAT(OFS_PARM1);
1723 case 0: // FILE_READ
1726 case 1: // FILE_APPEND
1729 case 2: // FILE_WRITE
1733 Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1734 PRVM_G_FLOAT(OFS_RETURN) = -3;
1737 filename = PRVM_G_STRING(OFS_PARM0);
1738 // .. is parent directory on many platforms
1739 // / is parent directory on Amiga
1740 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1741 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1742 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1744 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1745 PRVM_G_FLOAT(OFS_RETURN) = -4;
1748 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1749 if (VM_FILES[filenum] == NULL)
1750 PRVM_G_FLOAT(OFS_RETURN) = -1;
1752 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1759 fclose(float fhandle)
1762 //void(float fhandle) fclose = #111; // closes a file
1763 void VM_fclose(void)
1767 VM_SAFEPARMCOUNT(1,VM_fclose);
1769 filenum = PRVM_G_FLOAT(OFS_PARM0);
1770 if (filenum < 0 || filenum >= MAX_VMFILES)
1772 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1775 if (VM_FILES[filenum] == NULL)
1777 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1780 FS_Close(VM_FILES[filenum]);
1781 VM_FILES[filenum] = NULL;
1788 string fgets(float fhandle)
1791 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1795 static char string[VM_STRINGTEMP_LENGTH];
1798 VM_SAFEPARMCOUNT(1,VM_fgets);
1800 filenum = PRVM_G_FLOAT(OFS_PARM0);
1801 if (filenum < 0 || filenum >= MAX_VMFILES)
1803 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1806 if (VM_FILES[filenum] == NULL)
1808 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1814 c = FS_Getc(VM_FILES[filenum]);
1815 if (c == '\r' || c == '\n' || c < 0)
1817 if (end < VM_STRINGTEMP_LENGTH - 1)
1821 // remove \n following \r
1823 c = FS_Getc(VM_FILES[filenum]);
1824 if (developer.integer)
1825 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1827 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1829 PRVM_G_INT(OFS_RETURN) = 0;
1836 fputs(float fhandle, string s)
1839 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1843 char string[VM_STRINGTEMP_LENGTH];
1846 VM_SAFEPARMCOUNT(2,VM_fputs);
1848 filenum = PRVM_G_FLOAT(OFS_PARM0);
1849 if (filenum < 0 || filenum >= MAX_VMFILES)
1851 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1854 if (VM_FILES[filenum] == NULL)
1856 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1859 VM_VarString(1, string, sizeof(string));
1860 if ((stringlength = strlen(string)))
1861 FS_Write(VM_FILES[filenum], string, stringlength);
1862 if (developer.integer)
1863 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1870 float strlen(string s)
1873 //float(string s) strlen = #114; // returns how many characters are in a string
1874 void VM_strlen(void)
1878 VM_SAFEPARMCOUNT(1,VM_strlen);
1880 s = PRVM_G_STRING(OFS_PARM0);
1882 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1884 PRVM_G_FLOAT(OFS_RETURN) = 0;
1891 string strcat(string,string,...[string])
1894 //string(string s1, string s2) strcat = #115;
1895 // concatenates two strings (for example "abc", "def" would return "abcdef")
1896 // and returns as a tempstring
1897 void VM_strcat(void)
1902 PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
1904 s = VM_GetTempString();
1905 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1906 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1913 string substring(string s, float start, float length)
1916 // string(string s, float start, float length) substring = #116;
1917 // returns a section of a string as a tempstring
1918 void VM_substring(void)
1920 int i, start, length;
1923 VM_SAFEPARMCOUNT(3,VM_substring);
1925 string = VM_GetTempString();
1926 s = PRVM_G_STRING(OFS_PARM0);
1927 start = PRVM_G_FLOAT(OFS_PARM1);
1928 length = PRVM_G_FLOAT(OFS_PARM2);
1931 for (i = 0;i < start && *s;i++, s++);
1932 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1935 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1942 vector stov(string s)
1945 //vector(string s) stov = #117; // returns vector value from a string
1948 char string[VM_STRINGTEMP_LENGTH];
1950 VM_SAFEPARMCOUNT(1,VM_stov);
1952 VM_VarString(0, string, sizeof(string));
1953 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1960 string strzone(string s)
1963 //string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
1964 void VM_strzone(void)
1968 VM_SAFEPARMCOUNT(1,VM_strzone);
1970 in = PRVM_G_STRING(OFS_PARM0);
1971 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1973 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1983 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
1984 void VM_strunzone(void)
1986 VM_SAFEPARMCOUNT(1,VM_strunzone);
1988 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1993 VM_command (used by client and menu)
1995 clientcommand(float client, string s) (for client and menu)
1998 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1999 //this function originally written by KrimZon, made shorter by LordHavoc
2000 void VM_clcommand (void)
2002 client_t *temp_client;
2005 VM_SAFEPARMCOUNT(2,VM_clcommand);
2007 i = PRVM_G_FLOAT(OFS_PARM0);
2008 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2010 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
2014 temp_client = host_client;
2015 host_client = svs.clients + i;
2016 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2017 host_client = temp_client;
2025 float tokenize(string s)
2028 //float(string s) tokenize = #441;
2029 // takes apart a string into individal words (access them with argv), returns how many
2030 // this function originally written by KrimZon, made shorter by LordHavoc
2031 static char **tokens = NULL;
2032 static int max_tokens, num_tokens = 0;
2033 void VM_tokenize (void)
2038 VM_SAFEPARMCOUNT(1,VM_tokenize);
2040 str = PRVM_G_STRING(OFS_PARM0);
2045 for (i=0;i<num_tokens;i++)
2051 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2052 max_tokens = strlen(str);
2054 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2056 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2057 strcpy(tokens[num_tokens], com_token);
2060 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2067 string argv(float n)
2070 //string(float n) argv = #442;
2071 // returns a word from the tokenized string (returns nothing for an invalid index)
2072 // this function originally written by KrimZon, made shorter by LordHavoc
2077 VM_SAFEPARMCOUNT(1,VM_argv);
2079 token_num = PRVM_G_FLOAT(OFS_PARM0);
2080 if (token_num >= 0 && token_num < num_tokens)
2081 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2083 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2087 //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
2088 void PF_setattachment (void)
2090 edict_t *e = G_EDICT(OFS_PARM0);
2091 edict_t *tagentity = G_EDICT(OFS_PARM1);
2092 char *tagname = G_STRING(OFS_PARM2);
2097 if (tagentity == NULL)
2098 tagentity = sv.edicts;
2100 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2102 v->edict = EDICT_TO_PROG(tagentity);
2104 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2107 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2109 modelindex = (int)tagentity->v->modelindex;
2110 if (modelindex >= 0 && modelindex < MAX_MODELS)
2112 model = sv.models[modelindex];
2113 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2114 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2115 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2117 if (v->_float == 0 && model->alias.aliasnum_tags)
2118 for (i = 0;i < model->alias.aliasnum_tags;i++)
2119 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2122 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(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name);
2125 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(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity));
2136 void VM_isserver(void)
2138 VM_SAFEPARMCOUNT(0,VM_serverstate);
2140 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2150 void VM_clientcount(void)
2152 VM_SAFEPARMCOUNT(0,VM_clientcount);
2154 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2164 void VM_clientstate(void)
2166 VM_SAFEPARMCOUNT(0,VM_clientstate);
2168 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2175 float getostype(void)
2177 */ // not used at the moment -> not included in the common list
2178 void VM_getostype(void)
2180 VM_SAFEPARMCOUNT(0,VM_getostype);
2185 OS_MAC - not supported
2189 PRVM_G_FLOAT(OFS_RETURN) = 0;
2191 PRVM_G_FLOAT(OFS_RETURN) = 2;
2193 PRVM_G_FLOAT(OFS_RETURN) = 1;
2201 vector getmousepos()
2204 void VM_getmousepos(void)
2207 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2209 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2210 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2211 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2221 void VM_gettime(void)
2223 VM_SAFEPARMCOUNT(0,VM_gettime);
2225 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2232 loadfromdata(string data)
2235 void VM_loadfromdata(void)
2237 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2239 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2246 loadfromfile(string file)
2249 void VM_loadfromfile(void)
2254 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2256 filename = PRVM_G_STRING(OFS_PARM0);
2257 // .. is parent directory on many platforms
2258 // / is parent directory on Amiga
2259 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2260 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2261 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2263 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2264 PRVM_G_FLOAT(OFS_RETURN) = -4;
2268 // not conform with VM_fopen
2269 data = FS_LoadFile(filename, false);
2271 PRVM_G_FLOAT(OFS_RETURN) = -1;
2273 PRVM_ED_LoadFromFile(data);
2284 float mod(float val, float m)
2287 void VM_modulo(void)
2290 VM_SAFEPARMCOUNT(2,VM_module);
2292 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2293 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2295 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2298 void VM_Search_Init(void)
2300 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2303 void VM_Search_Reset(void)
2306 // reset the fssearch list
2307 for(i = 0; i < MAX_VMSEARCHES; i++)
2308 if(VM_SEARCHLIST[i])
2309 FS_FreeSearch(VM_SEARCHLIST[i]);
2310 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2317 float search_begin(string pattern, float caseinsensitive, float quiet)
2320 void VM_search_begin(void)
2324 int caseinsens, quiet;
2326 VM_SAFEPARMCOUNT(3, VM_search_begin);
2328 pattern = PRVM_G_STRING(OFS_PARM0);
2330 VM_CheckEmptyString(pattern);
2332 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2333 quiet = PRVM_G_FLOAT(OFS_PARM2);
2335 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2336 if(!VM_SEARCHLIST[handle])
2339 if(handle >= MAX_VMSEARCHES)
2341 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2342 PRVM_G_FLOAT(OFS_RETURN) = -2;
2346 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2347 PRVM_G_FLOAT(OFS_RETURN) = -1;
2349 PRVM_G_FLOAT(OFS_RETURN) = handle;
2356 void search_end(float handle)
2359 void VM_search_end(void)
2362 VM_SAFEPARMCOUNT(1, VM_search_end);
2364 handle = PRVM_G_FLOAT(OFS_PARM0);
2366 if(handle < 0 || handle >= MAX_VMSEARCHES)
2368 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2371 if(VM_SEARCHLIST[handle] == NULL)
2373 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2377 FS_FreeSearch(VM_SEARCHLIST[handle]);
2378 VM_SEARCHLIST[handle] = NULL;
2385 float search_getsize(float handle)
2388 void VM_search_getsize(void)
2391 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2393 handle = PRVM_G_FLOAT(OFS_PARM0);
2395 if(handle < 0 || handle >= MAX_VMSEARCHES)
2397 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2400 if(VM_SEARCHLIST[handle] == NULL)
2402 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2406 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2411 VM_search_getfilename
2413 string search_getfilename(float handle, float num)
2416 void VM_search_getfilename(void)
2418 int handle, filenum;
2420 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2422 handle = PRVM_G_FLOAT(OFS_PARM0);
2423 filenum = PRVM_G_FLOAT(OFS_PARM1);
2425 if(handle < 0 || handle >= MAX_VMSEARCHES)
2427 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2430 if(VM_SEARCHLIST[handle] == NULL)
2432 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2435 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2437 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2441 tmp = VM_GetTempString();
2442 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2444 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2451 string chr(float ascii)
2457 VM_SAFEPARMCOUNT(1, VM_chr);
2459 tmp = VM_GetTempString();
2460 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2463 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2466 //=============================================================================
2467 // Draw builtins (client & menu)
2473 float iscachedpic(string pic)
2476 void VM_iscachedpic(void)
2478 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2480 // drawq hasnt such a function, thus always return true
2481 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2488 string precache_pic(string pic)
2491 void VM_precache_pic(void)
2495 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2497 s = PRVM_G_STRING(OFS_PARM0);
2498 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2501 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2503 VM_CheckEmptyString (s);
2505 if(!Draw_CachePic(s))
2506 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2516 void VM_freepic(void)
2520 VM_SAFEPARMCOUNT(1,VM_freepic);
2522 s = PRVM_G_STRING(OFS_PARM0);
2525 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2527 VM_CheckEmptyString (s);
2536 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2539 void VM_drawcharacter(void)
2541 float *pos,*scale,*rgb;
2544 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2546 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2549 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2550 PRVM_G_FLOAT(OFS_RETURN) = -1;
2554 pos = PRVM_G_VECTOR(OFS_PARM0);
2555 scale = PRVM_G_VECTOR(OFS_PARM2);
2556 rgb = PRVM_G_VECTOR(OFS_PARM3);
2557 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2559 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2561 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2562 PRVM_G_FLOAT(OFS_RETURN) = -2;
2566 if(pos[2] || scale[2])
2567 Con_Printf("VM_drawcharacter: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2569 if(!scale[0] || !scale[1])
2571 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2572 PRVM_G_FLOAT(OFS_RETURN) = -3;
2576 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2577 PRVM_G_FLOAT(OFS_RETURN) = 1;
2584 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2587 void VM_drawstring(void)
2589 float *pos,*scale,*rgb;
2592 VM_SAFEPARMCOUNT(6,VM_drawstring);
2594 string = PRVM_G_STRING(OFS_PARM1);
2597 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2598 PRVM_G_FLOAT(OFS_RETURN) = -1;
2602 VM_CheckEmptyString(string);
2604 pos = PRVM_G_VECTOR(OFS_PARM0);
2605 scale = PRVM_G_VECTOR(OFS_PARM2);
2606 rgb = PRVM_G_VECTOR(OFS_PARM3);
2607 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2609 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2611 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2612 PRVM_G_FLOAT(OFS_RETURN) = -2;
2616 if(!scale[0] || !scale[1])
2618 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2619 PRVM_G_FLOAT(OFS_RETURN) = -3;
2623 if(pos[2] || scale[2])
2624 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2626 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2627 PRVM_G_FLOAT(OFS_RETURN) = 1;
2633 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2636 void VM_drawpic(void)
2639 float *size, *pos, *rgb;
2642 VM_SAFEPARMCOUNT(6,VM_drawpic);
2644 pic = PRVM_G_STRING(OFS_PARM1);
2648 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2649 PRVM_G_FLOAT(OFS_RETURN) = -1;
2653 VM_CheckEmptyString (pic);
2655 // is pic cached ? no function yet for that
2658 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2659 PRVM_G_FLOAT(OFS_RETURN) = -4;
2663 pos = PRVM_G_VECTOR(OFS_PARM0);
2664 size = PRVM_G_VECTOR(OFS_PARM2);
2665 rgb = PRVM_G_VECTOR(OFS_PARM3);
2666 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2668 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2670 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2671 PRVM_G_FLOAT(OFS_RETURN) = -2;
2675 if(pos[2] || size[2])
2676 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2678 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2679 PRVM_G_FLOAT(OFS_RETURN) = 1;
2686 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2689 void VM_drawfill(void)
2691 float *size, *pos, *rgb;
2694 VM_SAFEPARMCOUNT(5,VM_drawfill);
2697 pos = PRVM_G_VECTOR(OFS_PARM0);
2698 size = PRVM_G_VECTOR(OFS_PARM1);
2699 rgb = PRVM_G_VECTOR(OFS_PARM2);
2700 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2702 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2704 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2705 PRVM_G_FLOAT(OFS_RETURN) = -2;
2709 if(pos[2] || size[2])
2710 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2712 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2713 PRVM_G_FLOAT(OFS_RETURN) = 1;
2720 drawsetcliparea(float x, float y, float width, float height)
2723 void VM_drawsetcliparea(void)
2726 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2728 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2729 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2730 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2731 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2733 DrawQ_SetClipArea(x,y,w,h);
2738 VM_drawresetcliparea
2743 void VM_drawresetcliparea(void)
2745 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2747 DrawQ_ResetClipArea();
2754 vector getimagesize(string pic)
2757 void VM_getimagesize(void)
2762 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2764 p = PRVM_G_STRING(OFS_PARM0);
2767 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2769 VM_CheckEmptyString (p);
2771 pic = Draw_CachePic (p);
2773 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2774 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2775 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2778 void VM_Cmd_Init(void)
2780 // only init the stuff for the current prog
2781 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
2786 void VM_Cmd_Reset(void)
2788 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2789 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2791 VM_Files_CloseAll();
2794 //============================================================================
2797 char *vm_sv_extensions =
2800 prvm_builtin_t vm_sv_builtins[] = {
2801 0 // to be consistent with the old vm
2804 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2806 void VM_SV_Cmd_Init(void)
2810 void VM_SV_Cmd_Reset(void)
2814 //============================================================================
2817 char *vm_cl_extensions =
2820 prvm_builtin_t vm_cl_builtins[] = {
2821 0 // to be consistent with the old vm
2824 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2826 void VM_CL_Cmd_Init(void)
2830 void VM_CL_Cmd_Reset(void)
2834 //============================================================================
2837 char *vm_m_extensions =
2844 setmousetarget(float target)
2847 void VM_M_setmousetarget(void)
2849 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2851 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2854 in_client_mouse = false;
2857 in_client_mouse = true;
2860 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2868 float getmousetarget
2871 void VM_M_getmousetarget(void)
2873 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2876 PRVM_G_FLOAT(OFS_RETURN) = 2;
2878 PRVM_G_FLOAT(OFS_RETURN) = 1;
2887 setkeydest(float dest)
2890 void VM_M_setkeydest(void)
2892 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2894 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2898 key_dest = key_game;
2902 key_dest = key_menu;
2906 // key_dest = key_message
2909 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2920 void VM_M_getkeydest(void)
2922 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2924 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2928 PRVM_G_FLOAT(OFS_RETURN) = 0;
2931 PRVM_G_FLOAT(OFS_RETURN) = 2;
2935 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2938 PRVM_G_FLOAT(OFS_RETURN) = 3;
2946 callfunction(...,string function_name)
2949 mfunction_t *PRVM_ED_FindFunction (const char *name);
2950 void VM_M_callfunction(void)
2956 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
2958 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
2961 PRVM_ERROR("VM_M_callfunction: null string !\n");
2963 VM_CheckEmptyString(s);
2965 func = PRVM_ED_FindFunction(s);
2968 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
2969 else if (func->first_statement < 0)
2971 // negative statements are built in functions
2972 int builtinnumber = -func->first_statement;
2973 prog->xfunction->builtinsprofile++;
2974 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
2975 prog->builtins[builtinnumber]();
2977 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
2982 PRVM_ExecuteProgram(func - prog->functions,"");
2991 float isfunction(string function_name)
2994 mfunction_t *PRVM_ED_FindFunction (const char *name);
2995 void VM_M_isfunction(void)
3000 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3002 s = PRVM_G_STRING(OFS_PARM0);
3005 PRVM_ERROR("VM_M_isfunction: null string !\n");
3007 VM_CheckEmptyString(s);
3009 func = PRVM_ED_FindFunction(s);
3012 PRVM_G_FLOAT(OFS_RETURN) = false;
3014 PRVM_G_FLOAT(OFS_RETURN) = true;
3021 writetofile(float fhandle, entity ent)
3024 void VM_M_writetofile(void)
3029 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3031 filenum = PRVM_G_FLOAT(OFS_PARM0);
3032 if (filenum < 0 || filenum >= MAX_VMFILES)
3034 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3037 if (VM_FILES[filenum] == NULL)
3039 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3043 ent = PRVM_G_EDICT(OFS_PARM1);
3046 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3050 PRVM_ED_Write (VM_FILES[filenum], ent);
3057 vector getresolution(float number)
3060 extern unsigned short video_resolutions[][2];
3061 void VM_M_getresolution(void)
3064 VM_SAFEPARMCOUNT(1, VM_getresolution);
3066 nr = PRVM_G_FLOAT(OFS_PARM0);
3069 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3070 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3071 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3078 string keynumtostring(float keynum)
3081 void VM_M_keynumtostring(void)
3085 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3087 keynum = PRVM_G_FLOAT(OFS_PARM0);
3089 tmp = VM_GetTempString();
3091 strcpy(tmp, Key_KeynumToString(keynum));
3093 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3098 VM_M_findkeysforcommand
3100 string findkeysforcommand(string command)
3102 the returned string is an altstring
3105 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3107 void M_FindKeysForCommand(char *command, int *keys);
3108 void VM_M_findkeysforcommand(void)
3114 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3116 cmd = PRVM_G_STRING(OFS_PARM0);
3118 VM_CheckEmptyString(cmd);
3120 (ret = VM_GetTempString())[0] = 0;
3122 M_FindKeysForCommand(cmd, keys);
3124 for(i = 0; i < NUMKEYS; i++)
3125 ret = strcat(ret, va(" \'%i\'", keys[i]));
3127 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3132 VM_M_gethostcachecount
3134 float gethostcachevalue(float type)
3145 void VM_M_gethostcachevalue( void )
3148 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3150 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3152 type = PRVM_G_FLOAT( OFS_PARM0 );
3153 if( type < 0 || type > 4 )
3154 Con_Printf ( "VM_M_gethostcachevalue: bad type %i!\n", type );
3158 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3161 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3164 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3167 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3170 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3177 VM_M_gethostcachestring
3179 string gethostcachestring(float type, float hostnr)
3187 void VM_M_gethostcachestring(void)
3192 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3194 PRVM_G_INT(OFS_RETURN) = 0;
3196 type = PRVM_G_FLOAT(OFS_PARM0);
3198 if(type < 0 || type > 2)
3200 Con_Printf("VM_M_gethostcachestring: bad string type requested!\n");
3204 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3206 if(hostnr < 0 || hostnr >= hostCacheCount)
3208 Con_Printf("VM_M_gethostcachestring: bad hostnr passed!\n");
3213 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3214 else if( type == 1 )
3215 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3217 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3220 prvm_builtin_t vm_m_builtins[] = {
3221 0, // to be consistent with the old vm
3222 // common builtings (mostly)
3299 VM_search_getfilename, // 77
3315 VM_WriteEntity, // 408
3331 VM_drawresetcliparea,
3332 VM_getimagesize,// 460
3341 VM_M_setmousetarget,
3342 VM_M_getmousetarget,
3347 VM_M_keynumtostring,
3348 VM_M_findkeysforcommand,// 610
3349 VM_M_gethostcachevalue,
3350 VM_M_gethostcachestring // 612
3353 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3355 void VM_M_Cmd_Init(void)
3360 void VM_M_Cmd_Reset(void)