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)
103 float altstr_count(string)
104 string altstr_prepare(string)
105 string altstr_get(string,float)
107 perhaps only : Menu : WriteMsg
108 ===============================
110 WriteByte(float data, float dest, float desto)
111 WriteChar(float data, float dest, float desto)
112 WriteShort(float data, float dest, float desto)
113 WriteLong(float data, float dest, float desto)
114 WriteAngle(float data, float dest, float desto)
115 WriteCoord(float data, float dest, float desto)
116 WriteString(string data, float dest, float desto)
117 WriteEntity(entity data, float dest, float desto)
119 Client & Menu : draw functions & video functions
120 ===================================================
122 float iscachedpic(string pic)
123 string precache_pic(string pic)
125 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
126 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
127 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
128 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
129 drawsetcliparea(float x, float y, float width, float height)
131 vector getimagesize(string pic)
133 float cin_open(string file, string name)
134 void cin_close(string name)
135 void cin_setstate(string name, float type)
136 float cin_getstate(string name)
137 void cin_restart(string name)
139 ==============================================================================
143 setkeydest(float dest)
145 setmousetarget(float target)
146 float getmousetarget(void)
148 callfunction(...,string function_name)
149 writetofile(float fhandle, entity ent)
150 float isfunction(string function_name)
151 vector getresolution(float number)
152 string keynumtostring(float keynum)
153 string findkeysforcommand(string command)
154 float gethostcachevalue(float type)
155 string gethostcachestring(float type, float hostnr)
157 parseentitydata(entity ent, string data)
160 #include "quakedef.h"
161 #include "progdefs.h"
163 #include "clprogdefs.h"
164 #include "mprogdefs.h"
166 #include "cl_video.h"
168 //============================================================================
169 // nice helper macros
171 #ifndef VM_NOPARMCHECK
172 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
174 #define VM_SAFEPARMCOUNT(p,f)
177 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
179 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
181 #define e10 0,0,0,0,0,0,0,0,0,0
182 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
183 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
185 //============================================================================
188 // string zone mempool
189 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
191 // temp string handling
192 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
193 #define VM_STRINGTEMP_BUFFERS 16
194 #define VM_STRINGTEMP_LENGTH 4096
195 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
196 static int vm_string_tempindex = 0;
199 #define MAX_VMFILES 256
200 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
201 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
203 qfile_t *vm_files[MAX_PRVMFILES];
205 // qc fs search handling
206 #define MAX_VMSEARCHES 128
207 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
208 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
210 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
212 static char *VM_GetTempString(void)
215 s = vm_string_temp[vm_string_tempindex];
216 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
220 void VM_CheckEmptyString (char *s)
223 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
226 //============================================================================
229 void VM_VarString(int first, char *out, int outlength)
235 outend = out + outlength - 1;
236 for (i = first;i < prog->argc && out < outend;i++)
238 s = PRVM_G_STRING((OFS_PARM0+i*3));
239 while (out < outend && *s)
249 returns true if the extension is supported by the server
251 checkextension(extensionname)
255 // kind of helper function
256 static qboolean checkextension(char *name)
262 for (e = prog->extensionstring;*e;e++)
269 while (*e && *e != ' ')
271 if (e - start == len)
272 if (!strncasecmp(start, name, len))
280 void VM_checkextension (void)
282 VM_SAFEPARMCOUNT(1,VM_checkextension);
284 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
291 This is a TERMINAL error, which will kill off the entire prog.
300 char string[VM_STRINGTEMP_LENGTH];
302 VM_VarString(0, string, sizeof(string));
303 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
306 ed = PRVM_G_EDICT(prog->self->ofs);
310 PRVM_ERROR ("%s: Program error", PRVM_NAME);
317 Dumps out self, then an error message. The program is aborted and self is
318 removed, but the level can continue.
323 void VM_objerror (void)
326 char string[VM_STRINGTEMP_LENGTH];
328 VM_VarString(0, string, sizeof(string));
329 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
332 ed = PRVM_G_EDICT (prog->self->ofs);
338 // objerror has to display the object fields -> else call
339 PRVM_ERROR ("VM_objecterror: self not defined !\n");
344 VM_print (actually used only by client and menu)
353 char string[VM_STRINGTEMP_LENGTH];
355 VM_VarString(0, string, sizeof(string));
363 broadcast print to everyone on server
368 void VM_bprint (void)
370 char string[VM_STRINGTEMP_LENGTH];
374 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
378 VM_VarString(0, string, sizeof(string));
379 SV_BroadcastPrint(string);
384 VM_sprint (menu & client but only if server.active == true)
386 single print to a specific client
388 sprint(float clientnum,...[string])
391 void VM_sprint (void)
395 char string[VM_STRINGTEMP_LENGTH];
397 //find client for this entity
398 clientnum = PRVM_G_FLOAT(OFS_PARM0);
399 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
401 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
405 client = svs.clients + clientnum;
406 VM_VarString(1, string, sizeof(string));
407 MSG_WriteChar(&client->message,svc_print);
408 MSG_WriteString(&client->message, string);
415 single print to the screen
417 centerprint(clientent, value)
420 void VM_centerprint (void)
422 char string[VM_STRINGTEMP_LENGTH];
424 VM_VarString(0, string, sizeof(string));
425 SCR_CenterPrint(string);
432 vector normalize(vector)
435 void VM_normalize (void)
441 VM_SAFEPARMCOUNT(1,VM_normalize);
443 value1 = PRVM_G_VECTOR(OFS_PARM0);
445 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
449 newvalue[0] = newvalue[1] = newvalue[2] = 0;
453 newvalue[0] = value1[0] * new;
454 newvalue[1] = value1[1] * new;
455 newvalue[2] = value1[2] * new;
458 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
473 VM_SAFEPARMCOUNT(1,VM_vlen);
475 value1 = PRVM_G_VECTOR(OFS_PARM0);
477 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
480 PRVM_G_FLOAT(OFS_RETURN) = new;
487 float vectoyaw(vector)
490 void VM_vectoyaw (void)
495 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
497 value1 = PRVM_G_VECTOR(OFS_PARM0);
499 if (value1[1] == 0 && value1[0] == 0)
503 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
508 PRVM_G_FLOAT(OFS_RETURN) = yaw;
516 vector vectoangles(vector)
519 void VM_vectoangles (void)
525 VM_SAFEPARMCOUNT(1,VM_vectoangles);
527 value1 = PRVM_G_VECTOR(OFS_PARM0);
529 if (value1[1] == 0 && value1[0] == 0)
539 // LordHavoc: optimized a bit
542 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
546 else if (value1[1] > 0)
551 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
552 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
557 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
558 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
559 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
566 Returns a number from 0<= num < 1
571 void VM_random (void)
573 VM_SAFEPARMCOUNT(0,VM_random);
575 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
582 Each entity can have eight independant sound sources, like voice,
585 Channel 0 is an auto-allocate channel, the others override anything
586 already running on that entity/channel pair.
588 An attenuation of 0 will play full volume everywhere in the level.
589 Larger attenuations will drop off.
602 entity = G_EDICT(OFS_PARM0);
603 channel = G_FLOAT(OFS_PARM1);
604 sample = G_STRING(OFS_PARM2);
605 volume = G_FLOAT(OFS_PARM3) * 255;
606 attenuation = G_FLOAT(OFS_PARM4);
608 if (volume < 0 || volume > 255)
609 Host_Error ("SV_StartSound: volume = %i", volume);
611 if (attenuation < 0 || attenuation > 4)
612 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
614 if (channel < 0 || channel > 7)
615 Host_Error ("SV_StartSound: channel = %i", channel);
617 SV_StartSound (entity, channel, sample, volume, attenuation);
625 localsound(string sample)
628 void VM_localsound(void)
632 VM_SAFEPARMCOUNT(1,VM_localsound);
634 s = PRVM_G_STRING(OFS_PARM0);
636 if(!S_LocalSound (s))
638 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
639 PRVM_G_FLOAT(OFS_RETURN) = -4;
643 PRVM_G_FLOAT(OFS_RETURN) = 1;
655 PRVM_ERROR ("%s: break statement", PRVM_NAME);
658 //============================================================================
664 Sends text over to the client's execution buffer
666 [localcmd (string) or]
670 void VM_localcmd (void)
672 VM_SAFEPARMCOUNT(1,VM_localcmd);
674 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
686 VM_SAFEPARMCOUNT(1,VM_cvar);
688 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
695 const string str_cvar (string)
698 void VM_str_cvar(void)
701 const char *cvar_string;
702 VM_SAFEPARMCOUNT(1,VM_str_cvar);
704 name = PRVM_G_STRING(OFS_PARM0);
707 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
709 VM_CheckEmptyString(name);
711 out = VM_GetTempString();
713 cvar_string = Cvar_VariableString(name);
715 strcpy(out, cvar_string);
717 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
724 void cvar_set (string,string)
727 void VM_cvar_set (void)
729 VM_SAFEPARMCOUNT(2,VM_cvar_set);
731 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
741 void VM_dprint (void)
743 char string[VM_STRINGTEMP_LENGTH];
744 if (developer.integer)
746 VM_VarString(0, string, sizeof(string));
747 Con_Printf("%s: %s", PRVM_NAME, string);
764 VM_SAFEPARMCOUNT(1, VM_ftos);
766 v = PRVM_G_FLOAT(OFS_PARM0);
768 s = VM_GetTempString();
769 if ((float)((int)v) == v)
770 sprintf(s, "%i", (int)v);
773 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
788 VM_SAFEPARMCOUNT(1,VM_fabs);
790 v = PRVM_G_FLOAT(OFS_PARM0);
791 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
806 VM_SAFEPARMCOUNT(1,VM_vtos);
808 s = VM_GetTempString();
809 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]);
810 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
825 VM_SAFEPARMCOUNT(1, VM_etos);
827 s = VM_GetTempString();
828 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
829 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
836 float stof(...[string])
841 char string[VM_STRINGTEMP_LENGTH];
842 VM_VarString(0, string, sizeof(string));
843 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
847 ========================
851 ========================
855 VM_SAFEPARMCOUNT(1, VM_itof);
856 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
860 ========================
864 ========================
869 VM_SAFEPARMCOUNT(1, VM_ftoi);
871 ent = PRVM_G_FLOAT(OFS_PARM0);
872 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
873 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
875 PRVM_G_INT(OFS_RETURN) = ent;
889 prog->xfunction->builtinsprofile += 20;
890 ed = PRVM_ED_Alloc();
902 void VM_remove (void)
905 prog->xfunction->builtinsprofile += 20;
907 VM_SAFEPARMCOUNT(1, VM_remove);
909 ed = PRVM_G_EDICT(OFS_PARM0);
910 // if (ed == prog->edicts)
911 // PRVM_ERROR ("remove: tried to remove world\n");
912 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
913 // Host_Error("remove: tried to remove a client\n");
921 entity find(entity start, .string field, string match)
932 VM_SAFEPARMCOUNT(3,VM_find);
934 e = PRVM_G_EDICTNUM(OFS_PARM0);
935 f = PRVM_G_INT(OFS_PARM1);
936 s = PRVM_G_STRING(OFS_PARM2);
940 // return reserved edict 0 (could be used for whatever the prog wants)
941 VM_RETURN_EDICT(prog->edicts);
945 for (e++ ; e < prog->num_edicts ; e++)
947 prog->xfunction->builtinsprofile++;
948 ed = PRVM_EDICT_NUM(e);
951 t = PRVM_E_STRING(ed,f);
961 VM_RETURN_EDICT(prog->edicts);
968 entity findfloat(entity start, .float field, float match)
969 entity findentity(entity start, .entity field, entity match)
972 // LordHavoc: added this for searching float, int, and entity reference fields
973 void VM_findfloat (void)
980 VM_SAFEPARMCOUNT(3,VM_findfloat);
982 e = PRVM_G_EDICTNUM(OFS_PARM0);
983 f = PRVM_G_INT(OFS_PARM1);
984 s = PRVM_G_FLOAT(OFS_PARM2);
986 for (e++ ; e < prog->num_edicts ; e++)
988 prog->xfunction->builtinsprofile++;
989 ed = PRVM_EDICT_NUM(e);
992 if (PRVM_E_FLOAT(ed,f) == s)
999 VM_RETURN_EDICT(prog->edicts);
1006 entity findchain(.string field, string match)
1009 int PRVM_ED_FindFieldOffset(const char *field);
1010 // chained search for strings in entity fields
1011 // entity(.string field, string match) findchain = #402;
1012 void VM_findchain (void)
1018 prvm_edict_t *ent, *chain;
1020 VM_SAFEPARMCOUNT(2,VM_findchain);
1022 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1023 if(!prog->flag & PRVM_FE_CHAIN)
1024 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1026 chain_of = PRVM_ED_FindFieldOffset ("chain");
1028 chain = prog->edicts;
1030 f = PRVM_G_INT(OFS_PARM0);
1031 s = PRVM_G_STRING(OFS_PARM1);
1034 VM_RETURN_EDICT(prog->edicts);
1038 ent = PRVM_NEXT_EDICT(prog->edicts);
1039 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1041 prog->xfunction->builtinsprofile++;
1044 t = PRVM_E_STRING(ent,f);
1050 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1054 VM_RETURN_EDICT(chain);
1061 entity findchainfloat(.string field, float match)
1062 entity findchainentity(.string field, entity match)
1065 // LordHavoc: chained search for float, int, and entity reference fields
1066 // entity(.string field, float match) findchainfloat = #403;
1067 void VM_findchainfloat (void)
1073 prvm_edict_t *ent, *chain;
1075 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1077 if(!prog->flag & PRVM_FE_CHAIN)
1078 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1080 chain_of = PRVM_ED_FindFieldOffset ("chain");
1082 chain = (prvm_edict_t *)prog->edicts;
1084 f = PRVM_G_INT(OFS_PARM0);
1085 s = PRVM_G_FLOAT(OFS_PARM1);
1087 ent = PRVM_NEXT_EDICT(prog->edicts);
1088 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1090 prog->xfunction->builtinsprofile++;
1093 if (PRVM_E_FLOAT(ent,f) != s)
1096 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1100 VM_RETURN_EDICT(chain);
1107 string precache_file(string)
1110 void VM_precache_file (void)
1111 { // precache_file is only used to copy files with qcc, it does nothing
1112 VM_SAFEPARMCOUNT(1,VM_precache_file);
1114 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1121 used instead of the other VM_precache_* functions in the builtin list
1125 void VM_precache_error (void)
1127 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1134 string precache_sound (string sample)
1137 void VM_precache_sound (void)
1141 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1143 s = PRVM_G_STRING(OFS_PARM0);
1144 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1145 VM_CheckEmptyString (s);
1147 if(!S_PrecacheSound (s,true, true))
1148 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1158 void VM_coredump (void)
1160 VM_SAFEPARMCOUNT(0,VM_coredump);
1162 Cbuf_AddText("prvm_edicts ");
1163 Cbuf_AddText(PRVM_NAME);
1174 void PRVM_StackTrace(void);
1175 void VM_stackdump (void)
1177 VM_SAFEPARMCOUNT(0, VM_stackdump);
1192 VM_SAFEPARMCOUNT(0, VM_crash);
1194 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1204 void VM_traceon (void)
1206 VM_SAFEPARMCOUNT(0,VM_traceon);
1218 void VM_traceoff (void)
1220 VM_SAFEPARMCOUNT(0,VM_traceoff);
1222 prog->trace = false;
1232 void VM_eprint (void)
1234 VM_SAFEPARMCOUNT(1,VM_eprint);
1236 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1250 VM_SAFEPARMCOUNT(1,VM_rint);
1252 f = PRVM_G_FLOAT(OFS_PARM0);
1254 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1256 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1266 void VM_floor (void)
1268 VM_SAFEPARMCOUNT(1,VM_floor);
1270 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1282 VM_SAFEPARMCOUNT(1,VM_ceil);
1284 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1292 entity nextent(entity)
1295 void VM_nextent (void)
1300 i = PRVM_G_EDICTNUM(OFS_PARM0);
1303 prog->xfunction->builtinsprofile++;
1305 if (i == prog->num_edicts)
1307 VM_RETURN_EDICT(prog->edicts);
1310 ent = PRVM_EDICT_NUM(i);
1311 if (!ent->p.e->free)
1313 VM_RETURN_EDICT(ent);
1320 ===============================================================================
1323 used only for client and menu
1324 severs uses VM_SV_...
1326 Write*(* data, float type, float to)
1328 ===============================================================================
1331 #define MSG_BROADCAST 0 // unreliable to all
1332 #define MSG_ONE 1 // reliable to one (msg_entity)
1333 #define MSG_ALL 2 // reliable to all
1334 #define MSG_INIT 3 // write to the init string
1336 sizebuf_t *VM_WriteDest (void)
1342 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1344 dest = G_FLOAT(OFS_PARM1);
1348 return &sv.datagram;
1351 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1352 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1353 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1355 return &svs.clients[destclient].message;
1358 return &sv.reliable_datagram;
1364 PRVM_ERROR ("WriteDest: bad destination");
1371 void VM_WriteByte (void)
1373 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1376 void VM_WriteChar (void)
1378 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1381 void VM_WriteShort (void)
1383 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1386 void VM_WriteLong (void)
1388 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1391 void VM_WriteAngle (void)
1393 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1396 void VM_WriteCoord (void)
1398 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1401 void VM_WriteString (void)
1403 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1406 void VM_WriteEntity (void)
1408 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1411 //=============================================================================
1418 changelevel(string map)
1421 void VM_changelevel (void)
1425 VM_SAFEPARMCOUNT(1, VM_changelevel);
1429 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1433 // make sure we don't issue two changelevels
1434 if (svs.changelevel_issued)
1436 svs.changelevel_issued = true;
1438 s = G_STRING(OFS_PARM0);
1439 Cbuf_AddText (va("changelevel %s\n",s));
1451 VM_SAFEPARMCOUNT(1,VM_sin);
1452 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1463 VM_SAFEPARMCOUNT(1,VM_cos);
1464 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1476 VM_SAFEPARMCOUNT(1,VM_sqrt);
1477 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1484 Returns a vector of length < 1 and > 0
1489 void VM_randomvec (void)
1494 VM_SAFEPARMCOUNT(0, VM_randomvec);
1499 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1500 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1501 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1503 while (DotProduct(temp, temp) >= 1);
1504 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1507 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1508 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1509 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1510 // length returned always > 0
1511 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1512 VectorScale(temp,length, temp);*/
1513 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1516 //=============================================================================
1522 float registercvar (string name, string value, float flags)
1525 void VM_registercvar (void)
1530 VM_SAFEPARMCOUNT(3,VM_registercvar);
1532 name = PRVM_G_STRING(OFS_PARM0);
1533 value = PRVM_G_STRING(OFS_PARM1);
1534 flags = PRVM_G_FLOAT(OFS_PARM2);
1535 PRVM_G_FLOAT(OFS_RETURN) = 0;
1537 if(flags > CVAR_MAXFLAGSVAL)
1540 // first check to see if it has already been defined
1541 if (Cvar_FindVar (name))
1544 // check for overlap with a command
1545 if (Cmd_Exists (name))
1547 Con_Printf("VM_registercvar: %s is a command\n", name);
1551 Cvar_Get(name, value, flags);
1553 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1560 returns the minimum of two supplied floats
1562 float min(float a, float b, ...[float])
1567 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1568 if (prog->argc == 2)
1569 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1570 else if (prog->argc >= 3)
1573 float f = PRVM_G_FLOAT(OFS_PARM0);
1574 for (i = 1;i < prog->argc;i++)
1575 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1576 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1577 PRVM_G_FLOAT(OFS_RETURN) = f;
1580 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1587 returns the maximum of two supplied floats
1589 float max(float a, float b, ...[float])
1594 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1595 if (prog->argc == 2)
1596 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1597 else if (prog->argc >= 3)
1600 float f = PRVM_G_FLOAT(OFS_PARM0);
1601 for (i = 1;i < prog->argc;i++)
1602 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1603 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1604 PRVM_G_FLOAT(OFS_RETURN) = f;
1607 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1614 returns number bounded by supplied range
1616 float bound(float min, float value, float max)
1619 void VM_bound (void)
1621 VM_SAFEPARMCOUNT(3,VM_bound);
1622 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1629 returns a raised to power b
1631 float pow(float a, float b)
1636 VM_SAFEPARMCOUNT(2,VM_pow);
1637 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1644 copies data from one entity to another
1646 copyentity(entity src, entity dst)
1649 void VM_copyentity (void)
1651 prvm_edict_t *in, *out;
1652 VM_SAFEPARMCOUNT(2,VM_copyentity);
1653 in = PRVM_G_EDICT(OFS_PARM0);
1654 out = PRVM_G_EDICT(OFS_PARM1);
1655 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1662 sets the color of a client and broadcasts the update to all connected clients
1664 setcolor(clientent, value)
1667 /*void PF_setcolor (void)
1673 entnum = G_EDICTNUM(OFS_PARM0);
1674 i = G_FLOAT(OFS_PARM1);
1676 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1678 Con_Print("tried to setcolor a non-client\n");
1682 client = svs.clients + entnum-1;
1683 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1686 client->old_colors = i;
1687 client->edict->v->team = (i & 15) + 1;
1689 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1690 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1691 MSG_WriteByte (&sv.reliable_datagram, i);
1694 void VM_Files_Init(void)
1696 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1699 void VM_Files_CloseAll(void)
1702 for (i = 0;i < MAX_VMFILES;i++)
1705 FS_Close(VM_FILES[i]);
1706 //VM_FILES[i] = NULL;
1708 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1715 float fopen(string filename, float mode)
1718 // float(string filename, float mode) fopen = #110;
1719 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1720 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1724 char *modestring, *filename;
1726 VM_SAFEPARMCOUNT(2,VM_fopen);
1728 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1729 if (VM_FILES[filenum] == NULL)
1731 if (filenum >= MAX_VMFILES)
1733 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1734 PRVM_G_FLOAT(OFS_RETURN) = -2;
1737 mode = PRVM_G_FLOAT(OFS_PARM1);
1740 case 0: // FILE_READ
1743 case 1: // FILE_APPEND
1746 case 2: // FILE_WRITE
1750 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1751 PRVM_G_FLOAT(OFS_RETURN) = -3;
1754 filename = PRVM_G_STRING(OFS_PARM0);
1755 // .. is parent directory on many platforms
1756 // / is parent directory on Amiga
1757 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1758 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1759 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1761 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1762 PRVM_G_FLOAT(OFS_RETURN) = -4;
1765 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1766 if (VM_FILES[filenum] == NULL && mode == 0)
1767 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1769 if (VM_FILES[filenum] == NULL)
1770 PRVM_G_FLOAT(OFS_RETURN) = -1;
1772 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1779 fclose(float fhandle)
1782 //void(float fhandle) fclose = #111; // closes a file
1783 void VM_fclose(void)
1787 VM_SAFEPARMCOUNT(1,VM_fclose);
1789 filenum = PRVM_G_FLOAT(OFS_PARM0);
1790 if (filenum < 0 || filenum >= MAX_VMFILES)
1792 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1795 if (VM_FILES[filenum] == NULL)
1797 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1800 FS_Close(VM_FILES[filenum]);
1801 VM_FILES[filenum] = NULL;
1808 string fgets(float fhandle)
1811 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1815 static char string[VM_STRINGTEMP_LENGTH];
1818 VM_SAFEPARMCOUNT(1,VM_fgets);
1820 filenum = PRVM_G_FLOAT(OFS_PARM0);
1821 if (filenum < 0 || filenum >= MAX_VMFILES)
1823 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1826 if (VM_FILES[filenum] == NULL)
1828 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1834 c = FS_Getc(VM_FILES[filenum]);
1835 if (c == '\r' || c == '\n' || c < 0)
1837 if (end < VM_STRINGTEMP_LENGTH - 1)
1841 // remove \n following \r
1843 c = FS_Getc(VM_FILES[filenum]);
1844 if (developer.integer)
1845 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1847 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1849 PRVM_G_INT(OFS_RETURN) = 0;
1856 fputs(float fhandle, string s)
1859 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1863 char string[VM_STRINGTEMP_LENGTH];
1866 VM_SAFEPARMCOUNT(2,VM_fputs);
1868 filenum = PRVM_G_FLOAT(OFS_PARM0);
1869 if (filenum < 0 || filenum >= MAX_VMFILES)
1871 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1874 if (VM_FILES[filenum] == NULL)
1876 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1879 VM_VarString(1, string, sizeof(string));
1880 if ((stringlength = strlen(string)))
1881 FS_Write(VM_FILES[filenum], string, stringlength);
1882 if (developer.integer)
1883 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1890 float strlen(string s)
1893 //float(string s) strlen = #114; // returns how many characters are in a string
1894 void VM_strlen(void)
1898 VM_SAFEPARMCOUNT(1,VM_strlen);
1900 s = PRVM_G_STRING(OFS_PARM0);
1902 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1904 PRVM_G_FLOAT(OFS_RETURN) = 0;
1911 string strcat(string,string,...[string])
1914 //string(string s1, string s2) strcat = #115;
1915 // concatenates two strings (for example "abc", "def" would return "abcdef")
1916 // and returns as a tempstring
1917 void VM_strcat(void)
1922 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1924 s = VM_GetTempString();
1925 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1926 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1933 string substring(string s, float start, float length)
1936 // string(string s, float start, float length) substring = #116;
1937 // returns a section of a string as a tempstring
1938 void VM_substring(void)
1940 int i, start, length;
1943 VM_SAFEPARMCOUNT(3,VM_substring);
1945 string = VM_GetTempString();
1946 s = PRVM_G_STRING(OFS_PARM0);
1947 start = PRVM_G_FLOAT(OFS_PARM1);
1948 length = PRVM_G_FLOAT(OFS_PARM2);
1951 for (i = 0;i < start && *s;i++, s++);
1952 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1955 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1962 vector stov(string s)
1965 //vector(string s) stov = #117; // returns vector value from a string
1968 char string[VM_STRINGTEMP_LENGTH];
1970 VM_SAFEPARMCOUNT(1,VM_stov);
1972 VM_VarString(0, string, sizeof(string));
1973 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1980 string strzone(string s)
1983 //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)
1984 void VM_strzone(void)
1988 VM_SAFEPARMCOUNT(1,VM_strzone);
1990 in = PRVM_G_STRING(OFS_PARM0);
1991 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1993 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2003 //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!!!)
2004 void VM_strunzone(void)
2007 VM_SAFEPARMCOUNT(1,VM_strunzone);
2009 str = PRVM_G_STRING(OFS_PARM0);
2010 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2011 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2018 VM_command (used by client and menu)
2020 clientcommand(float client, string s) (for client and menu)
2023 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2024 //this function originally written by KrimZon, made shorter by LordHavoc
2025 void VM_clcommand (void)
2027 client_t *temp_client;
2030 VM_SAFEPARMCOUNT(2,VM_clcommand);
2032 i = PRVM_G_FLOAT(OFS_PARM0);
2033 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2035 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2039 temp_client = host_client;
2040 host_client = svs.clients + i;
2041 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2042 host_client = temp_client;
2050 float tokenize(string s)
2053 //float(string s) tokenize = #441;
2054 // takes apart a string into individal words (access them with argv), returns how many
2055 // this function originally written by KrimZon, made shorter by LordHavoc
2056 static char **tokens = NULL;
2057 static int max_tokens, num_tokens = 0;
2058 void VM_tokenize (void)
2063 VM_SAFEPARMCOUNT(1,VM_tokenize);
2065 str = PRVM_G_STRING(OFS_PARM0);
2070 for (i=0;i<num_tokens;i++)
2076 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2077 max_tokens = strlen(str);
2079 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2081 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2082 strcpy(tokens[num_tokens], com_token);
2085 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2092 string argv(float n)
2095 //string(float n) argv = #442;
2096 // returns a word from the tokenized string (returns nothing for an invalid index)
2097 // this function originally written by KrimZon, made shorter by LordHavoc
2102 VM_SAFEPARMCOUNT(1,VM_argv);
2104 token_num = PRVM_G_FLOAT(OFS_PARM0);
2105 if (token_num >= 0 && token_num < num_tokens)
2106 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2108 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2112 //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)
2113 void PF_setattachment (void)
2115 edict_t *e = G_EDICT(OFS_PARM0);
2116 edict_t *tagentity = G_EDICT(OFS_PARM1);
2117 char *tagname = G_STRING(OFS_PARM2);
2122 if (tagentity == NULL)
2123 tagentity = sv.edicts;
2125 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2127 v->edict = EDICT_TO_PROG(tagentity);
2129 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2132 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2134 modelindex = (int)tagentity->v->modelindex;
2135 if (modelindex >= 0 && modelindex < MAX_MODELS)
2137 model = sv.models[modelindex];
2138 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2139 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2140 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2142 // FIXME: use a model function to get tag info (need to handle skeletal)
2143 if (v->_float == 0 && model->alias.aliasnum_tags)
2144 for (i = 0;i < model->alias.aliasnum_tags;i++)
2145 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2148 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);
2151 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));
2162 void VM_isserver(void)
2164 VM_SAFEPARMCOUNT(0,VM_serverstate);
2166 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2176 void VM_clientcount(void)
2178 VM_SAFEPARMCOUNT(0,VM_clientcount);
2180 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2190 void VM_clientstate(void)
2192 VM_SAFEPARMCOUNT(0,VM_clientstate);
2194 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2201 float getostype(void)
2203 */ // not used at the moment -> not included in the common list
2204 void VM_getostype(void)
2206 VM_SAFEPARMCOUNT(0,VM_getostype);
2211 OS_MAC - not supported
2215 PRVM_G_FLOAT(OFS_RETURN) = 0;
2217 PRVM_G_FLOAT(OFS_RETURN) = 2;
2219 PRVM_G_FLOAT(OFS_RETURN) = 1;
2227 vector getmousepos()
2230 void VM_getmousepos(void)
2233 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2235 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2236 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2237 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2247 void VM_gettime(void)
2249 VM_SAFEPARMCOUNT(0,VM_gettime);
2251 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2258 loadfromdata(string data)
2261 void VM_loadfromdata(void)
2263 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2265 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2269 ========================
2270 VM_M_parseentitydata
2272 parseentitydata(entity ent, string data)
2273 ========================
2275 void VM_M_parseentitydata(void)
2280 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2282 // get edict and test it
2283 ent = PRVM_G_EDICT(OFS_PARM0);
2285 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2287 data = PRVM_G_STRING(OFS_PARM1);
2289 // parse the opening brace
2290 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2291 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2293 PRVM_ED_ParseEdict (data, ent);
2300 loadfromfile(string file)
2303 void VM_loadfromfile(void)
2308 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2310 filename = PRVM_G_STRING(OFS_PARM0);
2311 // .. is parent directory on many platforms
2312 // / is parent directory on Amiga
2313 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2314 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2315 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2317 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2318 PRVM_G_FLOAT(OFS_RETURN) = -4;
2322 // not conform with VM_fopen
2323 data = FS_LoadFile(filename, tempmempool, false);
2325 PRVM_G_FLOAT(OFS_RETURN) = -1;
2327 PRVM_ED_LoadFromFile(data);
2338 float mod(float val, float m)
2341 void VM_modulo(void)
2344 VM_SAFEPARMCOUNT(2,VM_module);
2346 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2347 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2349 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2352 void VM_Search_Init(void)
2354 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2357 void VM_Search_Reset(void)
2360 // reset the fssearch list
2361 for(i = 0; i < MAX_VMSEARCHES; i++)
2362 if(VM_SEARCHLIST[i])
2363 FS_FreeSearch(VM_SEARCHLIST[i]);
2364 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2371 float search_begin(string pattern, float caseinsensitive, float quiet)
2374 void VM_search_begin(void)
2378 int caseinsens, quiet;
2380 VM_SAFEPARMCOUNT(3, VM_search_begin);
2382 pattern = PRVM_G_STRING(OFS_PARM0);
2384 VM_CheckEmptyString(pattern);
2386 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2387 quiet = PRVM_G_FLOAT(OFS_PARM2);
2389 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2390 if(!VM_SEARCHLIST[handle])
2393 if(handle >= MAX_VMSEARCHES)
2395 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2396 PRVM_G_FLOAT(OFS_RETURN) = -2;
2400 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2401 PRVM_G_FLOAT(OFS_RETURN) = -1;
2403 PRVM_G_FLOAT(OFS_RETURN) = handle;
2410 void search_end(float handle)
2413 void VM_search_end(void)
2416 VM_SAFEPARMCOUNT(1, VM_search_end);
2418 handle = PRVM_G_FLOAT(OFS_PARM0);
2420 if(handle < 0 || handle >= MAX_VMSEARCHES)
2422 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2425 if(VM_SEARCHLIST[handle] == NULL)
2427 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2431 FS_FreeSearch(VM_SEARCHLIST[handle]);
2432 VM_SEARCHLIST[handle] = NULL;
2439 float search_getsize(float handle)
2442 void VM_search_getsize(void)
2445 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2447 handle = PRVM_G_FLOAT(OFS_PARM0);
2449 if(handle < 0 || handle >= MAX_VMSEARCHES)
2451 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2454 if(VM_SEARCHLIST[handle] == NULL)
2456 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2460 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2465 VM_search_getfilename
2467 string search_getfilename(float handle, float num)
2470 void VM_search_getfilename(void)
2472 int handle, filenum;
2474 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2476 handle = PRVM_G_FLOAT(OFS_PARM0);
2477 filenum = PRVM_G_FLOAT(OFS_PARM1);
2479 if(handle < 0 || handle >= MAX_VMSEARCHES)
2481 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2484 if(VM_SEARCHLIST[handle] == NULL)
2486 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2489 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2491 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2495 tmp = VM_GetTempString();
2496 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2498 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2505 string chr(float ascii)
2511 VM_SAFEPARMCOUNT(1, VM_chr);
2513 tmp = VM_GetTempString();
2514 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2517 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2520 //=============================================================================
2521 // Draw builtins (client & menu)
2527 float iscachedpic(string pic)
2530 void VM_iscachedpic(void)
2532 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2534 // drawq hasnt such a function, thus always return true
2535 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2542 string precache_pic(string pic)
2545 void VM_precache_pic(void)
2549 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2551 s = PRVM_G_STRING(OFS_PARM0);
2552 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2555 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2557 VM_CheckEmptyString (s);
2559 if(!Draw_CachePic(s))
2560 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2570 void VM_freepic(void)
2574 VM_SAFEPARMCOUNT(1,VM_freepic);
2576 s = PRVM_G_STRING(OFS_PARM0);
2579 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2581 VM_CheckEmptyString (s);
2590 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2593 void VM_drawcharacter(void)
2595 float *pos,*scale,*rgb;
2598 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2600 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2603 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2604 PRVM_G_FLOAT(OFS_RETURN) = -1;
2608 pos = PRVM_G_VECTOR(OFS_PARM0);
2609 scale = PRVM_G_VECTOR(OFS_PARM2);
2610 rgb = PRVM_G_VECTOR(OFS_PARM3);
2611 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2613 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2615 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2616 PRVM_G_FLOAT(OFS_RETURN) = -2;
2620 if(pos[2] || scale[2])
2621 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")));
2623 if(!scale[0] || !scale[1])
2625 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2626 PRVM_G_FLOAT(OFS_RETURN) = -3;
2630 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2631 PRVM_G_FLOAT(OFS_RETURN) = 1;
2638 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2641 void VM_drawstring(void)
2643 float *pos,*scale,*rgb;
2646 VM_SAFEPARMCOUNT(6,VM_drawstring);
2648 string = PRVM_G_STRING(OFS_PARM1);
2651 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2652 PRVM_G_FLOAT(OFS_RETURN) = -1;
2656 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to the precolored letters, too?
2658 pos = PRVM_G_VECTOR(OFS_PARM0);
2659 scale = PRVM_G_VECTOR(OFS_PARM2);
2660 rgb = PRVM_G_VECTOR(OFS_PARM3);
2661 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2663 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2665 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2666 PRVM_G_FLOAT(OFS_RETURN) = -2;
2670 if(!scale[0] || !scale[1])
2672 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2673 PRVM_G_FLOAT(OFS_RETURN) = -3;
2677 if(pos[2] || scale[2])
2678 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")));
2680 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2681 PRVM_G_FLOAT(OFS_RETURN) = 1;
2687 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2690 void VM_drawpic(void)
2693 float *size, *pos, *rgb;
2696 VM_SAFEPARMCOUNT(6,VM_drawpic);
2698 pic = PRVM_G_STRING(OFS_PARM1);
2702 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2703 PRVM_G_FLOAT(OFS_RETURN) = -1;
2707 VM_CheckEmptyString (pic);
2709 // is pic cached ? no function yet for that
2712 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2713 PRVM_G_FLOAT(OFS_RETURN) = -4;
2717 pos = PRVM_G_VECTOR(OFS_PARM0);
2718 size = PRVM_G_VECTOR(OFS_PARM2);
2719 rgb = PRVM_G_VECTOR(OFS_PARM3);
2720 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2722 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2724 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2725 PRVM_G_FLOAT(OFS_RETURN) = -2;
2729 if(pos[2] || size[2])
2730 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")));
2732 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2733 PRVM_G_FLOAT(OFS_RETURN) = 1;
2740 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2743 void VM_drawfill(void)
2745 float *size, *pos, *rgb;
2748 VM_SAFEPARMCOUNT(5,VM_drawfill);
2751 pos = PRVM_G_VECTOR(OFS_PARM0);
2752 size = PRVM_G_VECTOR(OFS_PARM1);
2753 rgb = PRVM_G_VECTOR(OFS_PARM2);
2754 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2756 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2758 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2759 PRVM_G_FLOAT(OFS_RETURN) = -2;
2763 if(pos[2] || size[2])
2764 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")));
2766 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2767 PRVM_G_FLOAT(OFS_RETURN) = 1;
2774 drawsetcliparea(float x, float y, float width, float height)
2777 void VM_drawsetcliparea(void)
2780 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2782 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2783 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2784 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2785 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2787 DrawQ_SetClipArea(x, y, w, h);
2792 VM_drawresetcliparea
2797 void VM_drawresetcliparea(void)
2799 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2801 DrawQ_ResetClipArea();
2808 vector getimagesize(string pic)
2811 void VM_getimagesize(void)
2816 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2818 p = PRVM_G_STRING(OFS_PARM0);
2821 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2823 VM_CheckEmptyString (p);
2825 pic = Draw_CachePic (p);
2827 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2828 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2829 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2832 // CL_Video interface functions
2835 ========================
2838 float cin_open(string file, string name)
2839 ========================
2841 void VM_cin_open( void )
2846 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2848 file = PRVM_G_STRING( OFS_PARM0 );
2849 name = PRVM_G_STRING( OFS_PARM1 );
2851 VM_CheckEmptyString( file );
2852 VM_CheckEmptyString( name );
2854 if( CL_OpenVideo( file, name, MENUOWNER ) )
2855 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2857 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2861 ========================
2864 void cin_close(string name)
2865 ========================
2867 void VM_cin_close( void )
2871 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2873 name = PRVM_G_STRING( OFS_PARM0 );
2874 VM_CheckEmptyString( name );
2876 CL_CloseVideo( CL_GetVideo( name ) );
2880 ========================
2882 void cin_setstate(string name, float type)
2883 ========================
2885 void VM_cin_setstate( void )
2888 clvideostate_t state;
2891 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2893 name = PRVM_G_STRING( OFS_PARM0 );
2894 VM_CheckEmptyString( name );
2896 state = PRVM_G_FLOAT( OFS_PARM1 );
2898 video = CL_GetVideo( name );
2899 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2900 CL_SetVideoState( video, state );
2904 ========================
2907 float cin_getstate(string name)
2908 ========================
2910 void VM_cin_getstate( void )
2915 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2917 name = PRVM_G_STRING( OFS_PARM0 );
2918 VM_CheckEmptyString( name );
2920 video = CL_GetVideo( name );
2922 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2924 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2928 ========================
2931 void cin_restart(string name)
2932 ========================
2934 void VM_cin_restart( void )
2939 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2941 name = PRVM_G_STRING( OFS_PARM0 );
2942 VM_CheckEmptyString( name );
2944 video = CL_GetVideo( name );
2946 CL_RestartVideo( video );
2949 ////////////////////////////////////////
2950 // AltString functions
2951 ////////////////////////////////////////
2954 ========================
2957 float altstr_count(string)
2958 ========================
2960 void VM_altstr_count( void )
2965 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2967 altstr = PRVM_G_STRING( OFS_PARM0 );
2968 VM_CheckEmptyString( altstr );
2970 for( count = 0, pos = altstr ; *pos ; pos++ )
2971 if( *pos == '\\' && !*++pos )
2973 else if( *pos == '\'' )
2976 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2980 ========================
2983 string altstr_prepare(string)
2984 ========================
2986 void VM_altstr_prepare( void )
2992 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
2994 instr = PRVM_G_STRING( OFS_PARM0 );
2995 VM_CheckEmptyString( instr );
2996 outstr = VM_GetTempString();
2998 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3007 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3011 ========================
3014 string altstr_get(string, float)
3015 ========================
3017 void VM_altstr_get( void )
3019 char *altstr, *pos, *outstr, *out;
3022 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3024 altstr = PRVM_G_STRING( OFS_PARM0 );
3025 VM_CheckEmptyString( altstr );
3027 count = PRVM_G_FLOAT( OFS_PARM1 );
3028 count = count * 2 + 1;
3030 for( pos = altstr ; *pos && count ; pos++ )
3031 if( *pos == '\\' && !*++pos )
3033 else if( *pos == '\'' )
3037 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3041 outstr = VM_GetTempString();
3042 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3043 if( *pos == '\\' ) {
3048 } else if( *pos == '\'' )
3054 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3057 void VM_Cmd_Init(void)
3059 // only init the stuff for the current prog
3060 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3065 void VM_Cmd_Reset(void)
3067 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3068 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3069 memheader_t *header;
3072 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3073 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3076 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3077 CL_PurgeOwner( MENUOWNER );
3079 VM_Files_CloseAll();
3082 //============================================================================
3085 char *vm_sv_extensions =
3088 prvm_builtin_t vm_sv_builtins[] = {
3089 0 // to be consistent with the old vm
3092 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3094 void VM_SV_Cmd_Init(void)
3098 void VM_SV_Cmd_Reset(void)
3102 //============================================================================
3105 char *vm_cl_extensions =
3108 prvm_builtin_t vm_cl_builtins[] = {
3109 0 // to be consistent with the old vm
3112 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3114 void VM_CL_Cmd_Init(void)
3118 void VM_CL_Cmd_Reset(void)
3122 //============================================================================
3125 char *vm_m_extensions =
3132 setmousetarget(float target)
3135 void VM_M_setmousetarget(void)
3137 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3139 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3142 in_client_mouse = false;
3145 in_client_mouse = true;
3148 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3156 float getmousetarget
3159 void VM_M_getmousetarget(void)
3161 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3164 PRVM_G_FLOAT(OFS_RETURN) = 2;
3166 PRVM_G_FLOAT(OFS_RETURN) = 1;
3175 setkeydest(float dest)
3178 void VM_M_setkeydest(void)
3180 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3182 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3186 key_dest = key_game;
3190 key_dest = key_menu;
3194 // key_dest = key_message
3197 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3208 void VM_M_getkeydest(void)
3210 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3212 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3216 PRVM_G_FLOAT(OFS_RETURN) = 0;
3219 PRVM_G_FLOAT(OFS_RETURN) = 2;
3223 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3226 PRVM_G_FLOAT(OFS_RETURN) = 3;
3234 callfunction(...,string function_name)
3238 mfunction_t *PRVM_ED_FindFunction (const char *name);
3239 void VM_M_callfunction(void)
3245 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3247 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3250 PRVM_ERROR("VM_M_callfunction: null string !\n");
3252 VM_CheckEmptyString(s);
3254 func = PRVM_ED_FindFunction(s);
3257 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3258 else if (func->first_statement < 0)
3260 // negative statements are built in functions
3261 int builtinnumber = -func->first_statement;
3262 prog->xfunction->builtinsprofile++;
3263 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3264 prog->builtins[builtinnumber]();
3266 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3271 PRVM_ExecuteProgram(func - prog->functions,"");
3280 float isfunction(string function_name)
3283 mfunction_t *PRVM_ED_FindFunction (const char *name);
3284 void VM_M_isfunction(void)
3289 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3291 s = PRVM_G_STRING(OFS_PARM0);
3294 PRVM_ERROR("VM_M_isfunction: null string !\n");
3296 VM_CheckEmptyString(s);
3298 func = PRVM_ED_FindFunction(s);
3301 PRVM_G_FLOAT(OFS_RETURN) = false;
3303 PRVM_G_FLOAT(OFS_RETURN) = true;
3310 writetofile(float fhandle, entity ent)
3313 void VM_M_writetofile(void)
3318 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3320 filenum = PRVM_G_FLOAT(OFS_PARM0);
3321 if (filenum < 0 || filenum >= MAX_VMFILES)
3323 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3326 if (VM_FILES[filenum] == NULL)
3328 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3332 ent = PRVM_G_EDICT(OFS_PARM1);
3335 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3339 PRVM_ED_Write (VM_FILES[filenum], ent);
3346 vector getresolution(float number)
3349 extern unsigned short video_resolutions[][2];
3350 void VM_M_getresolution(void)
3353 VM_SAFEPARMCOUNT(1, VM_getresolution);
3355 nr = PRVM_G_FLOAT(OFS_PARM0);
3358 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3359 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3360 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3367 string keynumtostring(float keynum)
3370 void VM_M_keynumtostring(void)
3374 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3376 keynum = PRVM_G_FLOAT(OFS_PARM0);
3378 tmp = VM_GetTempString();
3380 strcpy(tmp, Key_KeynumToString(keynum));
3382 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3387 VM_M_findkeysforcommand
3389 string findkeysforcommand(string command)
3391 the returned string is an altstring
3394 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3396 void M_FindKeysForCommand(char *command, int *keys);
3397 void VM_M_findkeysforcommand(void)
3403 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3405 cmd = PRVM_G_STRING(OFS_PARM0);
3407 VM_CheckEmptyString(cmd);
3409 (ret = VM_GetTempString())[0] = 0;
3411 M_FindKeysForCommand(cmd, keys);
3413 for(i = 0; i < NUMKEYS; i++)
3414 ret = strcat(ret, va(" \'%i\'", keys[i]));
3416 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3421 VM_M_gethostcachecount
3423 float gethostcachevalue(float type)
3434 void VM_M_gethostcachevalue( void )
3437 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3439 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3441 type = PRVM_G_FLOAT( OFS_PARM0 );
3442 if( type < 0 || type > 4 )
3443 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3447 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3450 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3453 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3456 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3459 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3466 VM_M_gethostcachestring
3468 string gethostcachestring(float type, float hostnr)
3476 void VM_M_gethostcachestring(void)
3481 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3483 PRVM_G_INT(OFS_RETURN) = 0;
3485 type = PRVM_G_FLOAT(OFS_PARM0);
3487 if(type < 0 || type > 2)
3489 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3493 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3495 if(hostnr < 0 || hostnr >= hostCacheCount)
3497 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3502 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3503 else if( type == 1 )
3504 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3506 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3509 prvm_builtin_t vm_m_builtins[] = {
3510 0, // to be consistent with the old vm
3511 // common builtings (mostly)
3588 VM_search_getfilename, // 77
3592 VM_itof, // isString
3595 VM_altstr_get, // 84
3609 VM_WriteEntity, // 408
3625 VM_drawresetcliparea,
3626 VM_getimagesize,// 460
3631 VM_cin_restart, // 465
3640 VM_M_setmousetarget,
3641 VM_M_getmousetarget,
3646 VM_M_keynumtostring,
3647 VM_M_findkeysforcommand,// 610
3648 VM_M_gethostcachevalue,
3649 VM_M_gethostcachestring,
3650 VM_M_parseentitydata // 613
3653 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3655 void VM_M_Cmd_Init(void)
3660 void VM_M_Cmd_Reset(void)