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) !\n", PRVM_NAME);
368 VM_VarString(0, string, sizeof(string));
369 SV_BroadcastPrint(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 !\n", 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);
632 if(!S_GetCached(s, true))
634 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
635 PRVM_G_FLOAT(OFS_RETURN) = -4;
639 S_LocalSound(s, true);
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);
1112 if(S_GetCached(s, true))
1114 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1118 if(!S_PrecacheSound(s,true, true))
1119 Con_Printf("VM_precache_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_Print("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 && mode == 0)
1750 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1752 if (VM_FILES[filenum] == NULL)
1753 PRVM_G_FLOAT(OFS_RETURN) = -1;
1755 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1762 fclose(float fhandle)
1765 //void(float fhandle) fclose = #111; // closes a file
1766 void VM_fclose(void)
1770 VM_SAFEPARMCOUNT(1,VM_fclose);
1772 filenum = PRVM_G_FLOAT(OFS_PARM0);
1773 if (filenum < 0 || filenum >= MAX_VMFILES)
1775 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1778 if (VM_FILES[filenum] == NULL)
1780 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1783 FS_Close(VM_FILES[filenum]);
1784 VM_FILES[filenum] = NULL;
1791 string fgets(float fhandle)
1794 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1798 static char string[VM_STRINGTEMP_LENGTH];
1801 VM_SAFEPARMCOUNT(1,VM_fgets);
1803 filenum = PRVM_G_FLOAT(OFS_PARM0);
1804 if (filenum < 0 || filenum >= MAX_VMFILES)
1806 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1809 if (VM_FILES[filenum] == NULL)
1811 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1817 c = FS_Getc(VM_FILES[filenum]);
1818 if (c == '\r' || c == '\n' || c < 0)
1820 if (end < VM_STRINGTEMP_LENGTH - 1)
1824 // remove \n following \r
1826 c = FS_Getc(VM_FILES[filenum]);
1827 if (developer.integer)
1828 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1830 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1832 PRVM_G_INT(OFS_RETURN) = 0;
1839 fputs(float fhandle, string s)
1842 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1846 char string[VM_STRINGTEMP_LENGTH];
1849 VM_SAFEPARMCOUNT(2,VM_fputs);
1851 filenum = PRVM_G_FLOAT(OFS_PARM0);
1852 if (filenum < 0 || filenum >= MAX_VMFILES)
1854 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1857 if (VM_FILES[filenum] == NULL)
1859 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1862 VM_VarString(1, string, sizeof(string));
1863 if ((stringlength = strlen(string)))
1864 FS_Write(VM_FILES[filenum], string, stringlength);
1865 if (developer.integer)
1866 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1873 float strlen(string s)
1876 //float(string s) strlen = #114; // returns how many characters are in a string
1877 void VM_strlen(void)
1881 VM_SAFEPARMCOUNT(1,VM_strlen);
1883 s = PRVM_G_STRING(OFS_PARM0);
1885 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1887 PRVM_G_FLOAT(OFS_RETURN) = 0;
1894 string strcat(string,string,...[string])
1897 //string(string s1, string s2) strcat = #115;
1898 // concatenates two strings (for example "abc", "def" would return "abcdef")
1899 // and returns as a tempstring
1900 void VM_strcat(void)
1905 PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
1907 s = VM_GetTempString();
1908 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1909 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1916 string substring(string s, float start, float length)
1919 // string(string s, float start, float length) substring = #116;
1920 // returns a section of a string as a tempstring
1921 void VM_substring(void)
1923 int i, start, length;
1926 VM_SAFEPARMCOUNT(3,VM_substring);
1928 string = VM_GetTempString();
1929 s = PRVM_G_STRING(OFS_PARM0);
1930 start = PRVM_G_FLOAT(OFS_PARM1);
1931 length = PRVM_G_FLOAT(OFS_PARM2);
1934 for (i = 0;i < start && *s;i++, s++);
1935 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1938 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1945 vector stov(string s)
1948 //vector(string s) stov = #117; // returns vector value from a string
1951 char string[VM_STRINGTEMP_LENGTH];
1953 VM_SAFEPARMCOUNT(1,VM_stov);
1955 VM_VarString(0, string, sizeof(string));
1956 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1963 string strzone(string s)
1966 //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)
1967 void VM_strzone(void)
1971 VM_SAFEPARMCOUNT(1,VM_strzone);
1973 in = PRVM_G_STRING(OFS_PARM0);
1974 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1976 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1986 //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!!!)
1987 void VM_strunzone(void)
1989 VM_SAFEPARMCOUNT(1,VM_strunzone);
1991 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1996 VM_command (used by client and menu)
1998 clientcommand(float client, string s) (for client and menu)
2001 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2002 //this function originally written by KrimZon, made shorter by LordHavoc
2003 void VM_clcommand (void)
2005 client_t *temp_client;
2008 VM_SAFEPARMCOUNT(2,VM_clcommand);
2010 i = PRVM_G_FLOAT(OFS_PARM0);
2011 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2013 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2017 temp_client = host_client;
2018 host_client = svs.clients + i;
2019 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2020 host_client = temp_client;
2028 float tokenize(string s)
2031 //float(string s) tokenize = #441;
2032 // takes apart a string into individal words (access them with argv), returns how many
2033 // this function originally written by KrimZon, made shorter by LordHavoc
2034 static char **tokens = NULL;
2035 static int max_tokens, num_tokens = 0;
2036 void VM_tokenize (void)
2041 VM_SAFEPARMCOUNT(1,VM_tokenize);
2043 str = PRVM_G_STRING(OFS_PARM0);
2048 for (i=0;i<num_tokens;i++)
2054 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2055 max_tokens = strlen(str);
2057 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2059 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2060 strcpy(tokens[num_tokens], com_token);
2063 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2070 string argv(float n)
2073 //string(float n) argv = #442;
2074 // returns a word from the tokenized string (returns nothing for an invalid index)
2075 // this function originally written by KrimZon, made shorter by LordHavoc
2080 VM_SAFEPARMCOUNT(1,VM_argv);
2082 token_num = PRVM_G_FLOAT(OFS_PARM0);
2083 if (token_num >= 0 && token_num < num_tokens)
2084 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2086 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2090 //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)
2091 void PF_setattachment (void)
2093 edict_t *e = G_EDICT(OFS_PARM0);
2094 edict_t *tagentity = G_EDICT(OFS_PARM1);
2095 char *tagname = G_STRING(OFS_PARM2);
2100 if (tagentity == NULL)
2101 tagentity = sv.edicts;
2103 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2105 v->edict = EDICT_TO_PROG(tagentity);
2107 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2110 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2112 modelindex = (int)tagentity->v->modelindex;
2113 if (modelindex >= 0 && modelindex < MAX_MODELS)
2115 model = sv.models[modelindex];
2116 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2117 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2118 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2120 if (v->_float == 0 && model->alias.aliasnum_tags)
2121 for (i = 0;i < model->alias.aliasnum_tags;i++)
2122 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2125 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);
2128 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));
2139 void VM_isserver(void)
2141 VM_SAFEPARMCOUNT(0,VM_serverstate);
2143 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2153 void VM_clientcount(void)
2155 VM_SAFEPARMCOUNT(0,VM_clientcount);
2157 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2167 void VM_clientstate(void)
2169 VM_SAFEPARMCOUNT(0,VM_clientstate);
2171 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2178 float getostype(void)
2180 */ // not used at the moment -> not included in the common list
2181 void VM_getostype(void)
2183 VM_SAFEPARMCOUNT(0,VM_getostype);
2188 OS_MAC - not supported
2192 PRVM_G_FLOAT(OFS_RETURN) = 0;
2194 PRVM_G_FLOAT(OFS_RETURN) = 2;
2196 PRVM_G_FLOAT(OFS_RETURN) = 1;
2204 vector getmousepos()
2207 void VM_getmousepos(void)
2210 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2212 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2213 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2214 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2224 void VM_gettime(void)
2226 VM_SAFEPARMCOUNT(0,VM_gettime);
2228 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2235 loadfromdata(string data)
2238 void VM_loadfromdata(void)
2240 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2242 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2249 loadfromfile(string file)
2252 void VM_loadfromfile(void)
2257 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2259 filename = PRVM_G_STRING(OFS_PARM0);
2260 // .. is parent directory on many platforms
2261 // / is parent directory on Amiga
2262 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2263 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2264 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2266 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2267 PRVM_G_FLOAT(OFS_RETURN) = -4;
2271 // not conform with VM_fopen
2272 data = FS_LoadFile(filename, tempmempool, false);
2274 PRVM_G_FLOAT(OFS_RETURN) = -1;
2276 PRVM_ED_LoadFromFile(data);
2287 float mod(float val, float m)
2290 void VM_modulo(void)
2293 VM_SAFEPARMCOUNT(2,VM_module);
2295 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2296 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2298 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2301 void VM_Search_Init(void)
2303 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2306 void VM_Search_Reset(void)
2309 // reset the fssearch list
2310 for(i = 0; i < MAX_VMSEARCHES; i++)
2311 if(VM_SEARCHLIST[i])
2312 FS_FreeSearch(VM_SEARCHLIST[i]);
2313 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2320 float search_begin(string pattern, float caseinsensitive, float quiet)
2323 void VM_search_begin(void)
2327 int caseinsens, quiet;
2329 VM_SAFEPARMCOUNT(3, VM_search_begin);
2331 pattern = PRVM_G_STRING(OFS_PARM0);
2333 VM_CheckEmptyString(pattern);
2335 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2336 quiet = PRVM_G_FLOAT(OFS_PARM2);
2338 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2339 if(!VM_SEARCHLIST[handle])
2342 if(handle >= MAX_VMSEARCHES)
2344 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2345 PRVM_G_FLOAT(OFS_RETURN) = -2;
2349 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2350 PRVM_G_FLOAT(OFS_RETURN) = -1;
2352 PRVM_G_FLOAT(OFS_RETURN) = handle;
2359 void search_end(float handle)
2362 void VM_search_end(void)
2365 VM_SAFEPARMCOUNT(1, VM_search_end);
2367 handle = PRVM_G_FLOAT(OFS_PARM0);
2369 if(handle < 0 || handle >= MAX_VMSEARCHES)
2371 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2374 if(VM_SEARCHLIST[handle] == NULL)
2376 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2380 FS_FreeSearch(VM_SEARCHLIST[handle]);
2381 VM_SEARCHLIST[handle] = NULL;
2388 float search_getsize(float handle)
2391 void VM_search_getsize(void)
2394 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2396 handle = PRVM_G_FLOAT(OFS_PARM0);
2398 if(handle < 0 || handle >= MAX_VMSEARCHES)
2400 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2403 if(VM_SEARCHLIST[handle] == NULL)
2405 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2409 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2414 VM_search_getfilename
2416 string search_getfilename(float handle, float num)
2419 void VM_search_getfilename(void)
2421 int handle, filenum;
2423 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2425 handle = PRVM_G_FLOAT(OFS_PARM0);
2426 filenum = PRVM_G_FLOAT(OFS_PARM1);
2428 if(handle < 0 || handle >= MAX_VMSEARCHES)
2430 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2433 if(VM_SEARCHLIST[handle] == NULL)
2435 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2438 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2440 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2444 tmp = VM_GetTempString();
2445 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2447 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2454 string chr(float ascii)
2460 VM_SAFEPARMCOUNT(1, VM_chr);
2462 tmp = VM_GetTempString();
2463 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2466 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2469 //=============================================================================
2470 // Draw builtins (client & menu)
2476 float iscachedpic(string pic)
2479 void VM_iscachedpic(void)
2481 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2483 // drawq hasnt such a function, thus always return true
2484 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2491 string precache_pic(string pic)
2494 void VM_precache_pic(void)
2498 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2500 s = PRVM_G_STRING(OFS_PARM0);
2501 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2504 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2506 VM_CheckEmptyString (s);
2508 if(!Draw_CachePic(s))
2509 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2519 void VM_freepic(void)
2523 VM_SAFEPARMCOUNT(1,VM_freepic);
2525 s = PRVM_G_STRING(OFS_PARM0);
2528 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2530 VM_CheckEmptyString (s);
2539 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2542 void VM_drawcharacter(void)
2544 float *pos,*scale,*rgb;
2547 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2549 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2552 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2553 PRVM_G_FLOAT(OFS_RETURN) = -1;
2557 pos = PRVM_G_VECTOR(OFS_PARM0);
2558 scale = PRVM_G_VECTOR(OFS_PARM2);
2559 rgb = PRVM_G_VECTOR(OFS_PARM3);
2560 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2562 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2564 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2565 PRVM_G_FLOAT(OFS_RETURN) = -2;
2569 if(pos[2] || scale[2])
2570 Con_Printf("VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2572 if(!scale[0] || !scale[1])
2574 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2575 PRVM_G_FLOAT(OFS_RETURN) = -3;
2579 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2580 PRVM_G_FLOAT(OFS_RETURN) = 1;
2587 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2590 void VM_drawstring(void)
2592 float *pos,*scale,*rgb;
2595 VM_SAFEPARMCOUNT(6,VM_drawstring);
2597 string = PRVM_G_STRING(OFS_PARM1);
2600 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2601 PRVM_G_FLOAT(OFS_RETURN) = -1;
2605 VM_CheckEmptyString(string);
2607 pos = PRVM_G_VECTOR(OFS_PARM0);
2608 scale = PRVM_G_VECTOR(OFS_PARM2);
2609 rgb = PRVM_G_VECTOR(OFS_PARM3);
2610 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2612 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2614 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2615 PRVM_G_FLOAT(OFS_RETURN) = -2;
2619 if(!scale[0] || !scale[1])
2621 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2622 PRVM_G_FLOAT(OFS_RETURN) = -3;
2626 if(pos[2] || scale[2])
2627 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2629 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2630 PRVM_G_FLOAT(OFS_RETURN) = 1;
2636 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2639 void VM_drawpic(void)
2642 float *size, *pos, *rgb;
2645 VM_SAFEPARMCOUNT(6,VM_drawpic);
2647 pic = PRVM_G_STRING(OFS_PARM1);
2651 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2652 PRVM_G_FLOAT(OFS_RETURN) = -1;
2656 VM_CheckEmptyString (pic);
2658 // is pic cached ? no function yet for that
2661 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2662 PRVM_G_FLOAT(OFS_RETURN) = -4;
2666 pos = PRVM_G_VECTOR(OFS_PARM0);
2667 size = PRVM_G_VECTOR(OFS_PARM2);
2668 rgb = PRVM_G_VECTOR(OFS_PARM3);
2669 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2671 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2673 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2674 PRVM_G_FLOAT(OFS_RETURN) = -2;
2678 if(pos[2] || size[2])
2679 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2681 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2682 PRVM_G_FLOAT(OFS_RETURN) = 1;
2689 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2692 void VM_drawfill(void)
2694 float *size, *pos, *rgb;
2697 VM_SAFEPARMCOUNT(5,VM_drawfill);
2700 pos = PRVM_G_VECTOR(OFS_PARM0);
2701 size = PRVM_G_VECTOR(OFS_PARM1);
2702 rgb = PRVM_G_VECTOR(OFS_PARM2);
2703 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2705 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2707 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2708 PRVM_G_FLOAT(OFS_RETURN) = -2;
2712 if(pos[2] || size[2])
2713 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2715 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2716 PRVM_G_FLOAT(OFS_RETURN) = 1;
2723 drawsetcliparea(float x, float y, float width, float height)
2726 void VM_drawsetcliparea(void)
2729 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2731 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2732 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2733 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2734 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2736 DrawQ_SetClipArea(x,y,w,h);
2741 VM_drawresetcliparea
2746 void VM_drawresetcliparea(void)
2748 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2750 DrawQ_ResetClipArea();
2757 vector getimagesize(string pic)
2760 void VM_getimagesize(void)
2765 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2767 p = PRVM_G_STRING(OFS_PARM0);
2770 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2772 VM_CheckEmptyString (p);
2774 pic = Draw_CachePic (p);
2776 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2777 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2778 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2781 void VM_Cmd_Init(void)
2783 // only init the stuff for the current prog
2784 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2789 void VM_Cmd_Reset(void)
2791 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2792 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2794 VM_Files_CloseAll();
2797 //============================================================================
2800 char *vm_sv_extensions =
2803 prvm_builtin_t vm_sv_builtins[] = {
2804 0 // to be consistent with the old vm
2807 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2809 void VM_SV_Cmd_Init(void)
2813 void VM_SV_Cmd_Reset(void)
2817 //============================================================================
2820 char *vm_cl_extensions =
2823 prvm_builtin_t vm_cl_builtins[] = {
2824 0 // to be consistent with the old vm
2827 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2829 void VM_CL_Cmd_Init(void)
2833 void VM_CL_Cmd_Reset(void)
2837 //============================================================================
2840 char *vm_m_extensions =
2847 setmousetarget(float target)
2850 void VM_M_setmousetarget(void)
2852 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2854 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2857 in_client_mouse = false;
2860 in_client_mouse = true;
2863 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2871 float getmousetarget
2874 void VM_M_getmousetarget(void)
2876 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2879 PRVM_G_FLOAT(OFS_RETURN) = 2;
2881 PRVM_G_FLOAT(OFS_RETURN) = 1;
2890 setkeydest(float dest)
2893 void VM_M_setkeydest(void)
2895 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2897 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2901 key_dest = key_game;
2905 key_dest = key_menu;
2909 // key_dest = key_message
2912 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2923 void VM_M_getkeydest(void)
2925 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2927 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2931 PRVM_G_FLOAT(OFS_RETURN) = 0;
2934 PRVM_G_FLOAT(OFS_RETURN) = 2;
2938 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2941 PRVM_G_FLOAT(OFS_RETURN) = 3;
2949 callfunction(...,string function_name)
2952 mfunction_t *PRVM_ED_FindFunction (const char *name);
2953 void VM_M_callfunction(void)
2959 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
2961 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
2964 PRVM_ERROR("VM_M_callfunction: null string !\n");
2966 VM_CheckEmptyString(s);
2968 func = PRVM_ED_FindFunction(s);
2971 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
2972 else if (func->first_statement < 0)
2974 // negative statements are built in functions
2975 int builtinnumber = -func->first_statement;
2976 prog->xfunction->builtinsprofile++;
2977 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
2978 prog->builtins[builtinnumber]();
2980 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
2985 PRVM_ExecuteProgram(func - prog->functions,"");
2994 float isfunction(string function_name)
2997 mfunction_t *PRVM_ED_FindFunction (const char *name);
2998 void VM_M_isfunction(void)
3003 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3005 s = PRVM_G_STRING(OFS_PARM0);
3008 PRVM_ERROR("VM_M_isfunction: null string !\n");
3010 VM_CheckEmptyString(s);
3012 func = PRVM_ED_FindFunction(s);
3015 PRVM_G_FLOAT(OFS_RETURN) = false;
3017 PRVM_G_FLOAT(OFS_RETURN) = true;
3024 writetofile(float fhandle, entity ent)
3027 void VM_M_writetofile(void)
3032 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3034 filenum = PRVM_G_FLOAT(OFS_PARM0);
3035 if (filenum < 0 || filenum >= MAX_VMFILES)
3037 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3040 if (VM_FILES[filenum] == NULL)
3042 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3046 ent = PRVM_G_EDICT(OFS_PARM1);
3049 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3053 PRVM_ED_Write (VM_FILES[filenum], ent);
3060 vector getresolution(float number)
3063 extern unsigned short video_resolutions[][2];
3064 void VM_M_getresolution(void)
3067 VM_SAFEPARMCOUNT(1, VM_getresolution);
3069 nr = PRVM_G_FLOAT(OFS_PARM0);
3072 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3073 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3074 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3081 string keynumtostring(float keynum)
3084 void VM_M_keynumtostring(void)
3088 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3090 keynum = PRVM_G_FLOAT(OFS_PARM0);
3092 tmp = VM_GetTempString();
3094 strcpy(tmp, Key_KeynumToString(keynum));
3096 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3101 VM_M_findkeysforcommand
3103 string findkeysforcommand(string command)
3105 the returned string is an altstring
3108 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3110 void M_FindKeysForCommand(char *command, int *keys);
3111 void VM_M_findkeysforcommand(void)
3117 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3119 cmd = PRVM_G_STRING(OFS_PARM0);
3121 VM_CheckEmptyString(cmd);
3123 (ret = VM_GetTempString())[0] = 0;
3125 M_FindKeysForCommand(cmd, keys);
3127 for(i = 0; i < NUMKEYS; i++)
3128 ret = strcat(ret, va(" \'%i\'", keys[i]));
3130 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3135 VM_M_gethostcachecount
3137 float gethostcachevalue(float type)
3148 void VM_M_gethostcachevalue( void )
3151 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3153 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3155 type = PRVM_G_FLOAT( OFS_PARM0 );
3156 if( type < 0 || type > 4 )
3157 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3161 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3164 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3167 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3170 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3173 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3180 VM_M_gethostcachestring
3182 string gethostcachestring(float type, float hostnr)
3190 void VM_M_gethostcachestring(void)
3195 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3197 PRVM_G_INT(OFS_RETURN) = 0;
3199 type = PRVM_G_FLOAT(OFS_PARM0);
3201 if(type < 0 || type > 2)
3203 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3207 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3209 if(hostnr < 0 || hostnr >= hostCacheCount)
3211 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3216 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3217 else if( type == 1 )
3218 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3220 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3223 prvm_builtin_t vm_m_builtins[] = {
3224 0, // to be consistent with the old vm
3225 // common builtings (mostly)
3302 VM_search_getfilename, // 77
3318 VM_WriteEntity, // 408
3334 VM_drawresetcliparea,
3335 VM_getimagesize,// 460
3344 VM_M_setmousetarget,
3345 VM_M_getmousetarget,
3350 VM_M_keynumtostring,
3351 VM_M_findkeysforcommand,// 610
3352 VM_M_gethostcachevalue,
3353 VM_M_gethostcachestring // 612
3356 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3358 void VM_M_Cmd_Init(void)
3363 void VM_M_Cmd_Reset(void)