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)
106 string altstr_set(string altstr, float num, string set)
108 perhaps only : Menu : WriteMsg
109 ===============================
111 WriteByte(float data, float dest, float desto)
112 WriteChar(float data, float dest, float desto)
113 WriteShort(float data, float dest, float desto)
114 WriteLong(float data, float dest, float desto)
115 WriteAngle(float data, float dest, float desto)
116 WriteCoord(float data, float dest, float desto)
117 WriteString(string data, float dest, float desto)
118 WriteEntity(entity data, float dest, float desto)
120 Client & Menu : draw functions & video functions
121 ===================================================
123 float iscachedpic(string pic)
124 string precache_pic(string pic)
126 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
127 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
128 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
129 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
130 drawsetcliparea(float x, float y, float width, float height)
132 vector getimagesize(string pic)
134 float cin_open(string file, string name)
135 void cin_close(string name)
136 void cin_setstate(string name, float type)
137 float cin_getstate(string name)
138 void cin_restart(string name)
140 ==============================================================================
144 setkeydest(float dest)
146 setmousetarget(float target)
147 float getmousetarget()
149 callfunction(...,string function_name)
150 writetofile(float fhandle, entity ent)
151 float isfunction(string function_name)
152 vector getresolution(float number)
153 string keynumtostring(float keynum)
154 string findkeysforcommand(string command)
155 float gethostcachestat(float type)
156 string gethostcachestring(float fld, float hostnr)
158 parseentitydata(entity ent, string data)
160 float stringtokeynum(string key)
162 resethostcachemasks()
163 sethostcachemaskstring(float mask, float fld, string str)
164 sethostcachemasknumber(float mask, float fld, float num, float op)
166 sethostcachesort(float field, float descending)
168 float gethostcachenumber(float fld, float hostnr)
169 float gethostcacheindexforkey(string key)
170 addwantedhostcachekey(string key)
173 #include "quakedef.h"
174 #include "progdefs.h"
176 #include "clprogdefs.h"
177 #include "mprogdefs.h"
179 #include "cl_video.h"
181 //============================================================================
182 // nice helper macros
184 #ifndef VM_NOPARMCHECK
185 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
187 #define VM_SAFEPARMCOUNT(p,f)
190 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
192 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
194 #define e10 0,0,0,0,0,0,0,0,0,0
195 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
196 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
198 //============================================================================
201 // string zone mempool
202 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
204 // temp string handling
205 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
206 #define VM_STRINGTEMP_BUFFERS 16
207 #define VM_STRINGTEMP_LENGTH 4096
208 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
209 static int vm_string_tempindex = 0;
212 #define MAX_VMFILES 256
213 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
214 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
216 qfile_t *vm_files[MAX_PRVMFILES];
218 // qc fs search handling
219 #define MAX_VMSEARCHES 128
220 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
221 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
223 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
225 static char *VM_GetTempString(void)
228 s = vm_string_temp[vm_string_tempindex];
229 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
233 void VM_CheckEmptyString (char *s)
236 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
239 //============================================================================
242 void VM_VarString(int first, char *out, int outlength)
248 outend = out + outlength - 1;
249 for (i = first;i < prog->argc && out < outend;i++)
251 s = PRVM_G_STRING((OFS_PARM0+i*3));
252 while (out < outend && *s)
262 returns true if the extension is supported by the server
264 checkextension(extensionname)
268 // kind of helper function
269 static qboolean checkextension(char *name)
275 for (e = prog->extensionstring;*e;e++)
282 while (*e && *e != ' ')
284 if (e - start == len)
285 if (!strncasecmp(start, name, len))
293 void VM_checkextension (void)
295 VM_SAFEPARMCOUNT(1,VM_checkextension);
297 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
304 This is a TERMINAL error, which will kill off the entire prog.
313 char string[VM_STRINGTEMP_LENGTH];
315 VM_VarString(0, string, sizeof(string));
316 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
319 ed = PRVM_G_EDICT(prog->self->ofs);
323 PRVM_ERROR ("%s: Program error", PRVM_NAME);
330 Dumps out self, then an error message. The program is aborted and self is
331 removed, but the level can continue.
336 void VM_objerror (void)
339 char string[VM_STRINGTEMP_LENGTH];
341 VM_VarString(0, string, sizeof(string));
342 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
345 ed = PRVM_G_EDICT (prog->self->ofs);
351 // objerror has to display the object fields -> else call
352 PRVM_ERROR ("VM_objecterror: self not defined !\n");
357 VM_print (actually used only by client and menu)
366 char string[VM_STRINGTEMP_LENGTH];
368 VM_VarString(0, string, sizeof(string));
376 broadcast print to everyone on server
381 void VM_bprint (void)
383 char string[VM_STRINGTEMP_LENGTH];
387 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
391 VM_VarString(0, string, sizeof(string));
392 SV_BroadcastPrint(string);
397 VM_sprint (menu & client but only if server.active == true)
399 single print to a specific client
401 sprint(float clientnum,...[string])
404 void VM_sprint (void)
408 char string[VM_STRINGTEMP_LENGTH];
410 //find client for this entity
411 clientnum = PRVM_G_FLOAT(OFS_PARM0);
412 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
414 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
418 client = svs.clients + clientnum;
419 VM_VarString(1, string, sizeof(string));
420 MSG_WriteChar(&client->message,svc_print);
421 MSG_WriteString(&client->message, string);
428 single print to the screen
430 centerprint(clientent, value)
433 void VM_centerprint (void)
435 char string[VM_STRINGTEMP_LENGTH];
437 VM_VarString(0, string, sizeof(string));
438 SCR_CenterPrint(string);
445 vector normalize(vector)
448 void VM_normalize (void)
454 VM_SAFEPARMCOUNT(1,VM_normalize);
456 value1 = PRVM_G_VECTOR(OFS_PARM0);
458 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
462 newvalue[0] = newvalue[1] = newvalue[2] = 0;
466 newvalue[0] = value1[0] * new;
467 newvalue[1] = value1[1] * new;
468 newvalue[2] = value1[2] * new;
471 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
486 VM_SAFEPARMCOUNT(1,VM_vlen);
488 value1 = PRVM_G_VECTOR(OFS_PARM0);
490 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
493 PRVM_G_FLOAT(OFS_RETURN) = new;
500 float vectoyaw(vector)
503 void VM_vectoyaw (void)
508 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
510 value1 = PRVM_G_VECTOR(OFS_PARM0);
512 if (value1[1] == 0 && value1[0] == 0)
516 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
521 PRVM_G_FLOAT(OFS_RETURN) = yaw;
529 vector vectoangles(vector)
532 void VM_vectoangles (void)
538 VM_SAFEPARMCOUNT(1,VM_vectoangles);
540 value1 = PRVM_G_VECTOR(OFS_PARM0);
542 if (value1[1] == 0 && value1[0] == 0)
552 // LordHavoc: optimized a bit
555 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
559 else if (value1[1] > 0)
564 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
565 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
570 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
571 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
572 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
579 Returns a number from 0<= num < 1
584 void VM_random (void)
586 VM_SAFEPARMCOUNT(0,VM_random);
588 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
595 Each entity can have eight independant sound sources, like voice,
598 Channel 0 is an auto-allocate channel, the others override anything
599 already running on that entity/channel pair.
601 An attenuation of 0 will play full volume everywhere in the level.
602 Larger attenuations will drop off.
615 entity = G_EDICT(OFS_PARM0);
616 channel = G_FLOAT(OFS_PARM1);
617 sample = G_STRING(OFS_PARM2);
618 volume = G_FLOAT(OFS_PARM3) * 255;
619 attenuation = G_FLOAT(OFS_PARM4);
621 if (volume < 0 || volume > 255)
622 Host_Error ("SV_StartSound: volume = %i", volume);
624 if (attenuation < 0 || attenuation > 4)
625 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
627 if (channel < 0 || channel > 7)
628 Host_Error ("SV_StartSound: channel = %i", channel);
630 SV_StartSound (entity, channel, sample, volume, attenuation);
638 localsound(string sample)
641 void VM_localsound(void)
645 VM_SAFEPARMCOUNT(1,VM_localsound);
647 s = PRVM_G_STRING(OFS_PARM0);
649 if(!S_LocalSound (s))
651 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
652 PRVM_G_FLOAT(OFS_RETURN) = -4;
656 PRVM_G_FLOAT(OFS_RETURN) = 1;
668 PRVM_ERROR ("%s: break statement", PRVM_NAME);
671 //============================================================================
677 Sends text over to the client's execution buffer
679 [localcmd (string) or]
683 void VM_localcmd (void)
685 VM_SAFEPARMCOUNT(1,VM_localcmd);
687 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
699 VM_SAFEPARMCOUNT(1,VM_cvar);
701 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
708 const string str_cvar (string)
711 void VM_str_cvar(void)
714 const char *cvar_string;
715 VM_SAFEPARMCOUNT(1,VM_str_cvar);
717 name = PRVM_G_STRING(OFS_PARM0);
720 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
722 VM_CheckEmptyString(name);
724 out = VM_GetTempString();
726 cvar_string = Cvar_VariableString(name);
728 strcpy(out, cvar_string);
730 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
737 void cvar_set (string,string)
740 void VM_cvar_set (void)
742 VM_SAFEPARMCOUNT(2,VM_cvar_set);
744 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
754 void VM_dprint (void)
756 char string[VM_STRINGTEMP_LENGTH];
757 if (developer.integer)
759 VM_VarString(0, string, sizeof(string));
760 Con_Printf("%s: %s", PRVM_NAME, string);
777 VM_SAFEPARMCOUNT(1, VM_ftos);
779 v = PRVM_G_FLOAT(OFS_PARM0);
781 s = VM_GetTempString();
782 if ((float)((int)v) == v)
783 sprintf(s, "%i", (int)v);
786 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
801 VM_SAFEPARMCOUNT(1,VM_fabs);
803 v = PRVM_G_FLOAT(OFS_PARM0);
804 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
819 VM_SAFEPARMCOUNT(1,VM_vtos);
821 s = VM_GetTempString();
822 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]);
823 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
838 VM_SAFEPARMCOUNT(1, VM_etos);
840 s = VM_GetTempString();
841 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
842 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
849 float stof(...[string])
854 char string[VM_STRINGTEMP_LENGTH];
855 VM_VarString(0, string, sizeof(string));
856 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
860 ========================
864 ========================
868 VM_SAFEPARMCOUNT(1, VM_itof);
869 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
873 ========================
877 ========================
882 VM_SAFEPARMCOUNT(1, VM_ftoi);
884 ent = PRVM_G_FLOAT(OFS_PARM0);
885 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
886 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
888 PRVM_G_INT(OFS_RETURN) = ent;
902 prog->xfunction->builtinsprofile += 20;
903 ed = PRVM_ED_Alloc();
915 void VM_remove (void)
918 prog->xfunction->builtinsprofile += 20;
920 VM_SAFEPARMCOUNT(1, VM_remove);
922 ed = PRVM_G_EDICT(OFS_PARM0);
923 // if (ed == prog->edicts)
924 // PRVM_ERROR ("remove: tried to remove world\n");
925 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
926 // Host_Error("remove: tried to remove a client\n");
934 entity find(entity start, .string field, string match)
945 VM_SAFEPARMCOUNT(3,VM_find);
947 e = PRVM_G_EDICTNUM(OFS_PARM0);
948 f = PRVM_G_INT(OFS_PARM1);
949 s = PRVM_G_STRING(OFS_PARM2);
953 // return reserved edict 0 (could be used for whatever the prog wants)
954 VM_RETURN_EDICT(prog->edicts);
958 for (e++ ; e < prog->num_edicts ; e++)
960 prog->xfunction->builtinsprofile++;
961 ed = PRVM_EDICT_NUM(e);
964 t = PRVM_E_STRING(ed,f);
974 VM_RETURN_EDICT(prog->edicts);
981 entity findfloat(entity start, .float field, float match)
982 entity findentity(entity start, .entity field, entity match)
985 // LordHavoc: added this for searching float, int, and entity reference fields
986 void VM_findfloat (void)
993 VM_SAFEPARMCOUNT(3,VM_findfloat);
995 e = PRVM_G_EDICTNUM(OFS_PARM0);
996 f = PRVM_G_INT(OFS_PARM1);
997 s = PRVM_G_FLOAT(OFS_PARM2);
999 for (e++ ; e < prog->num_edicts ; e++)
1001 prog->xfunction->builtinsprofile++;
1002 ed = PRVM_EDICT_NUM(e);
1005 if (PRVM_E_FLOAT(ed,f) == s)
1007 VM_RETURN_EDICT(ed);
1012 VM_RETURN_EDICT(prog->edicts);
1019 entity findchain(.string field, string match)
1022 int PRVM_ED_FindFieldOffset(const char *field);
1023 // chained search for strings in entity fields
1024 // entity(.string field, string match) findchain = #402;
1025 void VM_findchain (void)
1031 prvm_edict_t *ent, *chain;
1033 VM_SAFEPARMCOUNT(2,VM_findchain);
1035 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1036 if(!prog->flag & PRVM_FE_CHAIN)
1037 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1039 chain_of = PRVM_ED_FindFieldOffset ("chain");
1041 chain = prog->edicts;
1043 f = PRVM_G_INT(OFS_PARM0);
1044 s = PRVM_G_STRING(OFS_PARM1);
1047 VM_RETURN_EDICT(prog->edicts);
1051 ent = PRVM_NEXT_EDICT(prog->edicts);
1052 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1054 prog->xfunction->builtinsprofile++;
1057 t = PRVM_E_STRING(ent,f);
1063 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1067 VM_RETURN_EDICT(chain);
1074 entity findchainfloat(.string field, float match)
1075 entity findchainentity(.string field, entity match)
1078 // LordHavoc: chained search for float, int, and entity reference fields
1079 // entity(.string field, float match) findchainfloat = #403;
1080 void VM_findchainfloat (void)
1086 prvm_edict_t *ent, *chain;
1088 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1090 if(!prog->flag & PRVM_FE_CHAIN)
1091 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1093 chain_of = PRVM_ED_FindFieldOffset ("chain");
1095 chain = (prvm_edict_t *)prog->edicts;
1097 f = PRVM_G_INT(OFS_PARM0);
1098 s = PRVM_G_FLOAT(OFS_PARM1);
1100 ent = PRVM_NEXT_EDICT(prog->edicts);
1101 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1103 prog->xfunction->builtinsprofile++;
1106 if (PRVM_E_FLOAT(ent,f) != s)
1109 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1113 VM_RETURN_EDICT(chain);
1120 string precache_file(string)
1123 void VM_precache_file (void)
1124 { // precache_file is only used to copy files with qcc, it does nothing
1125 VM_SAFEPARMCOUNT(1,VM_precache_file);
1127 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1134 used instead of the other VM_precache_* functions in the builtin list
1138 void VM_precache_error (void)
1140 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1147 string precache_sound (string sample)
1150 void VM_precache_sound (void)
1154 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1156 s = PRVM_G_STRING(OFS_PARM0);
1157 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1158 VM_CheckEmptyString (s);
1160 if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
1161 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1171 void VM_coredump (void)
1173 VM_SAFEPARMCOUNT(0,VM_coredump);
1175 Cbuf_AddText("prvm_edicts ");
1176 Cbuf_AddText(PRVM_NAME);
1187 void PRVM_StackTrace(void);
1188 void VM_stackdump (void)
1190 VM_SAFEPARMCOUNT(0, VM_stackdump);
1205 VM_SAFEPARMCOUNT(0, VM_crash);
1207 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1217 void VM_traceon (void)
1219 VM_SAFEPARMCOUNT(0,VM_traceon);
1231 void VM_traceoff (void)
1233 VM_SAFEPARMCOUNT(0,VM_traceoff);
1235 prog->trace = false;
1245 void VM_eprint (void)
1247 VM_SAFEPARMCOUNT(1,VM_eprint);
1249 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1263 VM_SAFEPARMCOUNT(1,VM_rint);
1265 f = PRVM_G_FLOAT(OFS_PARM0);
1267 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1269 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1279 void VM_floor (void)
1281 VM_SAFEPARMCOUNT(1,VM_floor);
1283 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1295 VM_SAFEPARMCOUNT(1,VM_ceil);
1297 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1305 entity nextent(entity)
1308 void VM_nextent (void)
1313 i = PRVM_G_EDICTNUM(OFS_PARM0);
1316 prog->xfunction->builtinsprofile++;
1318 if (i == prog->num_edicts)
1320 VM_RETURN_EDICT(prog->edicts);
1323 ent = PRVM_EDICT_NUM(i);
1324 if (!ent->p.e->free)
1326 VM_RETURN_EDICT(ent);
1333 ===============================================================================
1336 used only for client and menu
1337 severs uses VM_SV_...
1339 Write*(* data, float type, float to)
1341 ===============================================================================
1344 #define MSG_BROADCAST 0 // unreliable to all
1345 #define MSG_ONE 1 // reliable to one (msg_entity)
1346 #define MSG_ALL 2 // reliable to all
1347 #define MSG_INIT 3 // write to the init string
1349 sizebuf_t *VM_WriteDest (void)
1355 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1357 dest = G_FLOAT(OFS_PARM1);
1361 return &sv.datagram;
1364 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1365 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1366 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1368 return &svs.clients[destclient].message;
1371 return &sv.reliable_datagram;
1377 PRVM_ERROR ("WriteDest: bad destination");
1384 void VM_WriteByte (void)
1386 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1389 void VM_WriteChar (void)
1391 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1394 void VM_WriteShort (void)
1396 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1399 void VM_WriteLong (void)
1401 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1404 void VM_WriteAngle (void)
1406 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1409 void VM_WriteCoord (void)
1411 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1414 void VM_WriteString (void)
1416 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1419 void VM_WriteEntity (void)
1421 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1424 //=============================================================================
1431 changelevel(string map)
1434 void VM_changelevel (void)
1438 VM_SAFEPARMCOUNT(1, VM_changelevel);
1442 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1446 // make sure we don't issue two changelevels
1447 if (svs.changelevel_issued)
1449 svs.changelevel_issued = true;
1451 s = G_STRING(OFS_PARM0);
1452 Cbuf_AddText (va("changelevel %s\n",s));
1464 VM_SAFEPARMCOUNT(1,VM_sin);
1465 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1476 VM_SAFEPARMCOUNT(1,VM_cos);
1477 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1489 VM_SAFEPARMCOUNT(1,VM_sqrt);
1490 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1497 Returns a vector of length < 1 and > 0
1502 void VM_randomvec (void)
1507 VM_SAFEPARMCOUNT(0, VM_randomvec);
1512 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1513 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1514 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1516 while (DotProduct(temp, temp) >= 1);
1517 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1520 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1521 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1522 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1523 // length returned always > 0
1524 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1525 VectorScale(temp,length, temp);*/
1526 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1529 //=============================================================================
1535 float registercvar (string name, string value, float flags)
1538 void VM_registercvar (void)
1543 VM_SAFEPARMCOUNT(3,VM_registercvar);
1545 name = PRVM_G_STRING(OFS_PARM0);
1546 value = PRVM_G_STRING(OFS_PARM1);
1547 flags = PRVM_G_FLOAT(OFS_PARM2);
1548 PRVM_G_FLOAT(OFS_RETURN) = 0;
1550 if(flags > CVAR_MAXFLAGSVAL)
1553 // first check to see if it has already been defined
1554 if (Cvar_FindVar (name))
1557 // check for overlap with a command
1558 if (Cmd_Exists (name))
1560 Con_Printf("VM_registercvar: %s is a command\n", name);
1564 Cvar_Get(name, value, flags);
1566 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1573 returns the minimum of two supplied floats
1575 float min(float a, float b, ...[float])
1580 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1581 if (prog->argc == 2)
1582 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1583 else if (prog->argc >= 3)
1586 float f = PRVM_G_FLOAT(OFS_PARM0);
1587 for (i = 1;i < prog->argc;i++)
1588 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1589 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1590 PRVM_G_FLOAT(OFS_RETURN) = f;
1593 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1600 returns the maximum of two supplied floats
1602 float max(float a, float b, ...[float])
1607 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1608 if (prog->argc == 2)
1609 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1610 else if (prog->argc >= 3)
1613 float f = PRVM_G_FLOAT(OFS_PARM0);
1614 for (i = 1;i < prog->argc;i++)
1615 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1616 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1617 PRVM_G_FLOAT(OFS_RETURN) = f;
1620 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1627 returns number bounded by supplied range
1629 float bound(float min, float value, float max)
1632 void VM_bound (void)
1634 VM_SAFEPARMCOUNT(3,VM_bound);
1635 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1642 returns a raised to power b
1644 float pow(float a, float b)
1649 VM_SAFEPARMCOUNT(2,VM_pow);
1650 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1657 copies data from one entity to another
1659 copyentity(entity src, entity dst)
1662 void VM_copyentity (void)
1664 prvm_edict_t *in, *out;
1665 VM_SAFEPARMCOUNT(2,VM_copyentity);
1666 in = PRVM_G_EDICT(OFS_PARM0);
1667 out = PRVM_G_EDICT(OFS_PARM1);
1668 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1675 sets the color of a client and broadcasts the update to all connected clients
1677 setcolor(clientent, value)
1680 /*void PF_setcolor (void)
1686 entnum = G_EDICTNUM(OFS_PARM0);
1687 i = G_FLOAT(OFS_PARM1);
1689 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1691 Con_Print("tried to setcolor a non-client\n");
1695 client = svs.clients + entnum-1;
1696 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1699 client->old_colors = i;
1700 client->edict->v->team = (i & 15) + 1;
1702 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1703 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1704 MSG_WriteByte (&sv.reliable_datagram, i);
1707 void VM_Files_Init(void)
1709 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1712 void VM_Files_CloseAll(void)
1715 for (i = 0;i < MAX_VMFILES;i++)
1718 FS_Close(VM_FILES[i]);
1719 //VM_FILES[i] = NULL;
1721 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1728 float fopen(string filename, float mode)
1731 // float(string filename, float mode) fopen = #110;
1732 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1733 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1737 char *modestring, *filename;
1739 VM_SAFEPARMCOUNT(2,VM_fopen);
1741 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1742 if (VM_FILES[filenum] == NULL)
1744 if (filenum >= MAX_VMFILES)
1746 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1747 PRVM_G_FLOAT(OFS_RETURN) = -2;
1750 mode = PRVM_G_FLOAT(OFS_PARM1);
1753 case 0: // FILE_READ
1756 case 1: // FILE_APPEND
1759 case 2: // FILE_WRITE
1763 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1764 PRVM_G_FLOAT(OFS_RETURN) = -3;
1767 filename = PRVM_G_STRING(OFS_PARM0);
1768 // .. is parent directory on many platforms
1769 // / is parent directory on Amiga
1770 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1771 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1772 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1774 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1775 PRVM_G_FLOAT(OFS_RETURN) = -4;
1778 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1779 if (VM_FILES[filenum] == NULL && mode == 0)
1780 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1782 if (VM_FILES[filenum] == NULL)
1783 PRVM_G_FLOAT(OFS_RETURN) = -1;
1785 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1792 fclose(float fhandle)
1795 //void(float fhandle) fclose = #111; // closes a file
1796 void VM_fclose(void)
1800 VM_SAFEPARMCOUNT(1,VM_fclose);
1802 filenum = PRVM_G_FLOAT(OFS_PARM0);
1803 if (filenum < 0 || filenum >= MAX_VMFILES)
1805 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1808 if (VM_FILES[filenum] == NULL)
1810 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1813 FS_Close(VM_FILES[filenum]);
1814 VM_FILES[filenum] = NULL;
1821 string fgets(float fhandle)
1824 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1828 static char string[VM_STRINGTEMP_LENGTH];
1831 VM_SAFEPARMCOUNT(1,VM_fgets);
1833 filenum = PRVM_G_FLOAT(OFS_PARM0);
1834 if (filenum < 0 || filenum >= MAX_VMFILES)
1836 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1839 if (VM_FILES[filenum] == NULL)
1841 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1847 c = FS_Getc(VM_FILES[filenum]);
1848 if (c == '\r' || c == '\n' || c < 0)
1850 if (end < VM_STRINGTEMP_LENGTH - 1)
1854 // remove \n following \r
1856 c = FS_Getc(VM_FILES[filenum]);
1857 if (developer.integer >= 3)
1858 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1860 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1862 PRVM_G_INT(OFS_RETURN) = 0;
1869 fputs(float fhandle, string s)
1872 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1876 char string[VM_STRINGTEMP_LENGTH];
1879 VM_SAFEPARMCOUNT(2,VM_fputs);
1881 filenum = PRVM_G_FLOAT(OFS_PARM0);
1882 if (filenum < 0 || filenum >= MAX_VMFILES)
1884 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1887 if (VM_FILES[filenum] == NULL)
1889 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1892 VM_VarString(1, string, sizeof(string));
1893 if ((stringlength = strlen(string)))
1894 FS_Write(VM_FILES[filenum], string, stringlength);
1895 if (developer.integer)
1896 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1903 float strlen(string s)
1906 //float(string s) strlen = #114; // returns how many characters are in a string
1907 void VM_strlen(void)
1911 VM_SAFEPARMCOUNT(1,VM_strlen);
1913 s = PRVM_G_STRING(OFS_PARM0);
1915 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1917 PRVM_G_FLOAT(OFS_RETURN) = 0;
1924 string strcat(string,string,...[string])
1927 //string(string s1, string s2) strcat = #115;
1928 // concatenates two strings (for example "abc", "def" would return "abcdef")
1929 // and returns as a tempstring
1930 void VM_strcat(void)
1935 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1937 s = VM_GetTempString();
1938 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1939 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1946 string substring(string s, float start, float length)
1949 // string(string s, float start, float length) substring = #116;
1950 // returns a section of a string as a tempstring
1951 void VM_substring(void)
1953 int i, start, length;
1956 VM_SAFEPARMCOUNT(3,VM_substring);
1958 string = VM_GetTempString();
1959 s = PRVM_G_STRING(OFS_PARM0);
1960 start = PRVM_G_FLOAT(OFS_PARM1);
1961 length = PRVM_G_FLOAT(OFS_PARM2);
1964 for (i = 0;i < start && *s;i++, s++);
1965 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1968 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1975 vector stov(string s)
1978 //vector(string s) stov = #117; // returns vector value from a string
1981 char string[VM_STRINGTEMP_LENGTH];
1983 VM_SAFEPARMCOUNT(1,VM_stov);
1985 VM_VarString(0, string, sizeof(string));
1986 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1993 string strzone(string s)
1996 //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)
1997 void VM_strzone(void)
2001 VM_SAFEPARMCOUNT(1,VM_strzone);
2003 in = PRVM_G_STRING(OFS_PARM0);
2004 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
2006 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2016 //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!!!)
2017 void VM_strunzone(void)
2020 VM_SAFEPARMCOUNT(1,VM_strunzone);
2022 str = PRVM_G_STRING(OFS_PARM0);
2023 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2024 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2031 VM_command (used by client and menu)
2033 clientcommand(float client, string s) (for client and menu)
2036 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2037 //this function originally written by KrimZon, made shorter by LordHavoc
2038 void VM_clcommand (void)
2040 client_t *temp_client;
2043 VM_SAFEPARMCOUNT(2,VM_clcommand);
2045 i = PRVM_G_FLOAT(OFS_PARM0);
2046 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2048 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2052 temp_client = host_client;
2053 host_client = svs.clients + i;
2054 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2055 host_client = temp_client;
2063 float tokenize(string s)
2066 //float(string s) tokenize = #441;
2067 // takes apart a string into individal words (access them with argv), returns how many
2068 // this function originally written by KrimZon, made shorter by LordHavoc
2069 static char **tokens = NULL;
2070 static int max_tokens, num_tokens = 0;
2071 void VM_tokenize (void)
2076 VM_SAFEPARMCOUNT(1,VM_tokenize);
2078 str = PRVM_G_STRING(OFS_PARM0);
2083 for (i=0;i<num_tokens;i++)
2089 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2090 max_tokens = strlen(str);
2092 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2094 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2095 strcpy(tokens[num_tokens], com_token);
2098 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2105 string argv(float n)
2108 //string(float n) argv = #442;
2109 // returns a word from the tokenized string (returns nothing for an invalid index)
2110 // this function originally written by KrimZon, made shorter by LordHavoc
2115 VM_SAFEPARMCOUNT(1,VM_argv);
2117 token_num = PRVM_G_FLOAT(OFS_PARM0);
2118 if (token_num >= 0 && token_num < num_tokens)
2119 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2121 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2125 //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)
2126 void PF_setattachment (void)
2128 edict_t *e = G_EDICT(OFS_PARM0);
2129 edict_t *tagentity = G_EDICT(OFS_PARM1);
2130 char *tagname = G_STRING(OFS_PARM2);
2135 if (tagentity == NULL)
2136 tagentity = sv.edicts;
2138 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2140 v->edict = EDICT_TO_PROG(tagentity);
2142 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2145 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2147 modelindex = (int)tagentity->v->modelindex;
2148 if (modelindex >= 0 && modelindex < MAX_MODELS)
2150 model = sv.models[modelindex];
2151 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2152 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2153 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2155 // FIXME: use a model function to get tag info (need to handle skeletal)
2156 if (v->_float == 0 && model->alias.aliasnum_tags)
2157 for (i = 0;i < model->alias.aliasnum_tags;i++)
2158 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2161 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);
2164 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));
2175 void VM_isserver(void)
2177 VM_SAFEPARMCOUNT(0,VM_serverstate);
2179 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2189 void VM_clientcount(void)
2191 VM_SAFEPARMCOUNT(0,VM_clientcount);
2193 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2203 void VM_clientstate(void)
2205 VM_SAFEPARMCOUNT(0,VM_clientstate);
2207 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2214 float getostype(void)
2216 */ // not used at the moment -> not included in the common list
2217 void VM_getostype(void)
2219 VM_SAFEPARMCOUNT(0,VM_getostype);
2224 OS_MAC - not supported
2228 PRVM_G_FLOAT(OFS_RETURN) = 0;
2230 PRVM_G_FLOAT(OFS_RETURN) = 2;
2232 PRVM_G_FLOAT(OFS_RETURN) = 1;
2240 vector getmousepos()
2243 void VM_getmousepos(void)
2246 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2248 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2249 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2250 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2260 void VM_gettime(void)
2262 VM_SAFEPARMCOUNT(0,VM_gettime);
2264 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2271 loadfromdata(string data)
2274 void VM_loadfromdata(void)
2276 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2278 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2282 ========================
2283 VM_M_parseentitydata
2285 parseentitydata(entity ent, string data)
2286 ========================
2288 void VM_M_parseentitydata(void)
2293 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2295 // get edict and test it
2296 ent = PRVM_G_EDICT(OFS_PARM0);
2298 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2300 data = PRVM_G_STRING(OFS_PARM1);
2302 // parse the opening brace
2303 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2304 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2306 PRVM_ED_ParseEdict (data, ent);
2313 loadfromfile(string file)
2316 void VM_loadfromfile(void)
2321 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2323 filename = PRVM_G_STRING(OFS_PARM0);
2324 // .. is parent directory on many platforms
2325 // / is parent directory on Amiga
2326 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2327 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2328 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2330 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2331 PRVM_G_FLOAT(OFS_RETURN) = -4;
2335 // not conform with VM_fopen
2336 data = FS_LoadFile(filename, tempmempool, false);
2338 PRVM_G_FLOAT(OFS_RETURN) = -1;
2340 PRVM_ED_LoadFromFile(data);
2351 float mod(float val, float m)
2354 void VM_modulo(void)
2357 VM_SAFEPARMCOUNT(2,VM_module);
2359 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2360 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2362 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2365 void VM_Search_Init(void)
2367 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2370 void VM_Search_Reset(void)
2373 // reset the fssearch list
2374 for(i = 0; i < MAX_VMSEARCHES; i++)
2375 if(VM_SEARCHLIST[i])
2376 FS_FreeSearch(VM_SEARCHLIST[i]);
2377 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2384 float search_begin(string pattern, float caseinsensitive, float quiet)
2387 void VM_search_begin(void)
2391 int caseinsens, quiet;
2393 VM_SAFEPARMCOUNT(3, VM_search_begin);
2395 pattern = PRVM_G_STRING(OFS_PARM0);
2397 VM_CheckEmptyString(pattern);
2399 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2400 quiet = PRVM_G_FLOAT(OFS_PARM2);
2402 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2403 if(!VM_SEARCHLIST[handle])
2406 if(handle >= MAX_VMSEARCHES)
2408 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2409 PRVM_G_FLOAT(OFS_RETURN) = -2;
2413 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2414 PRVM_G_FLOAT(OFS_RETURN) = -1;
2416 PRVM_G_FLOAT(OFS_RETURN) = handle;
2423 void search_end(float handle)
2426 void VM_search_end(void)
2429 VM_SAFEPARMCOUNT(1, VM_search_end);
2431 handle = PRVM_G_FLOAT(OFS_PARM0);
2433 if(handle < 0 || handle >= MAX_VMSEARCHES)
2435 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2438 if(VM_SEARCHLIST[handle] == NULL)
2440 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2444 FS_FreeSearch(VM_SEARCHLIST[handle]);
2445 VM_SEARCHLIST[handle] = NULL;
2452 float search_getsize(float handle)
2455 void VM_search_getsize(void)
2458 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2460 handle = PRVM_G_FLOAT(OFS_PARM0);
2462 if(handle < 0 || handle >= MAX_VMSEARCHES)
2464 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2467 if(VM_SEARCHLIST[handle] == NULL)
2469 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2473 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2478 VM_search_getfilename
2480 string search_getfilename(float handle, float num)
2483 void VM_search_getfilename(void)
2485 int handle, filenum;
2487 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2489 handle = PRVM_G_FLOAT(OFS_PARM0);
2490 filenum = PRVM_G_FLOAT(OFS_PARM1);
2492 if(handle < 0 || handle >= MAX_VMSEARCHES)
2494 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2497 if(VM_SEARCHLIST[handle] == NULL)
2499 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2502 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2504 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2508 tmp = VM_GetTempString();
2509 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2511 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2518 string chr(float ascii)
2524 VM_SAFEPARMCOUNT(1, VM_chr);
2526 tmp = VM_GetTempString();
2527 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2530 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2533 //=============================================================================
2534 // Draw builtins (client & menu)
2540 float iscachedpic(string pic)
2543 void VM_iscachedpic(void)
2545 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2547 // drawq hasnt such a function, thus always return true
2548 PRVM_G_FLOAT(OFS_RETURN) = false;
2555 string precache_pic(string pic)
2558 void VM_precache_pic(void)
2562 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2564 s = PRVM_G_STRING(OFS_PARM0);
2565 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2568 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2570 VM_CheckEmptyString (s);
2572 if(!Draw_CachePic(s))
2573 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2583 void VM_freepic(void)
2587 VM_SAFEPARMCOUNT(1,VM_freepic);
2589 s = PRVM_G_STRING(OFS_PARM0);
2592 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2594 VM_CheckEmptyString (s);
2603 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2606 void VM_drawcharacter(void)
2608 float *pos,*scale,*rgb;
2611 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2613 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2616 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2617 PRVM_G_FLOAT(OFS_RETURN) = -1;
2621 pos = PRVM_G_VECTOR(OFS_PARM0);
2622 scale = PRVM_G_VECTOR(OFS_PARM2);
2623 rgb = PRVM_G_VECTOR(OFS_PARM3);
2624 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2626 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2628 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2629 PRVM_G_FLOAT(OFS_RETURN) = -2;
2633 if(pos[2] || scale[2])
2634 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")));
2636 if(!scale[0] || !scale[1])
2638 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2639 PRVM_G_FLOAT(OFS_RETURN) = -3;
2643 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2644 PRVM_G_FLOAT(OFS_RETURN) = 1;
2651 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2654 void VM_drawstring(void)
2656 float *pos,*scale,*rgb;
2659 VM_SAFEPARMCOUNT(6,VM_drawstring);
2661 string = PRVM_G_STRING(OFS_PARM1);
2664 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2665 PRVM_G_FLOAT(OFS_RETURN) = -1;
2669 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2671 pos = PRVM_G_VECTOR(OFS_PARM0);
2672 scale = PRVM_G_VECTOR(OFS_PARM2);
2673 rgb = PRVM_G_VECTOR(OFS_PARM3);
2674 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2676 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2678 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2679 PRVM_G_FLOAT(OFS_RETURN) = -2;
2683 if(!scale[0] || !scale[1])
2685 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2686 PRVM_G_FLOAT(OFS_RETURN) = -3;
2690 if(pos[2] || scale[2])
2691 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")));
2693 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2694 PRVM_G_FLOAT(OFS_RETURN) = 1;
2700 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2703 void VM_drawpic(void)
2706 float *size, *pos, *rgb;
2709 VM_SAFEPARMCOUNT(6,VM_drawpic);
2711 pic = PRVM_G_STRING(OFS_PARM1);
2715 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2716 PRVM_G_FLOAT(OFS_RETURN) = -1;
2720 VM_CheckEmptyString (pic);
2722 // is pic cached ? no function yet for that
2725 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2726 PRVM_G_FLOAT(OFS_RETURN) = -4;
2730 pos = PRVM_G_VECTOR(OFS_PARM0);
2731 size = PRVM_G_VECTOR(OFS_PARM2);
2732 rgb = PRVM_G_VECTOR(OFS_PARM3);
2733 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2735 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2737 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2738 PRVM_G_FLOAT(OFS_RETURN) = -2;
2742 if(pos[2] || size[2])
2743 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")));
2745 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2746 PRVM_G_FLOAT(OFS_RETURN) = 1;
2753 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2756 void VM_drawfill(void)
2758 float *size, *pos, *rgb;
2761 VM_SAFEPARMCOUNT(5,VM_drawfill);
2764 pos = PRVM_G_VECTOR(OFS_PARM0);
2765 size = PRVM_G_VECTOR(OFS_PARM1);
2766 rgb = PRVM_G_VECTOR(OFS_PARM2);
2767 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2769 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2771 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2772 PRVM_G_FLOAT(OFS_RETURN) = -2;
2776 if(pos[2] || size[2])
2777 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")));
2779 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2780 PRVM_G_FLOAT(OFS_RETURN) = 1;
2787 drawsetcliparea(float x, float y, float width, float height)
2790 void VM_drawsetcliparea(void)
2793 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2795 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2796 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2797 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2798 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2800 DrawQ_SetClipArea(x, y, w, h);
2805 VM_drawresetcliparea
2810 void VM_drawresetcliparea(void)
2812 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2814 DrawQ_ResetClipArea();
2821 vector getimagesize(string pic)
2824 void VM_getimagesize(void)
2829 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2831 p = PRVM_G_STRING(OFS_PARM0);
2834 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2836 VM_CheckEmptyString (p);
2838 pic = Draw_CachePic (p);
2840 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2841 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2842 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2845 // CL_Video interface functions
2848 ========================
2851 float cin_open(string file, string name)
2852 ========================
2854 void VM_cin_open( void )
2859 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2861 file = PRVM_G_STRING( OFS_PARM0 );
2862 name = PRVM_G_STRING( OFS_PARM1 );
2864 VM_CheckEmptyString( file );
2865 VM_CheckEmptyString( name );
2867 if( CL_OpenVideo( file, name, MENUOWNER ) )
2868 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2870 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2874 ========================
2877 void cin_close(string name)
2878 ========================
2880 void VM_cin_close( void )
2884 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2886 name = PRVM_G_STRING( OFS_PARM0 );
2887 VM_CheckEmptyString( name );
2889 CL_CloseVideo( CL_GetVideo( name ) );
2893 ========================
2895 void cin_setstate(string name, float type)
2896 ========================
2898 void VM_cin_setstate( void )
2901 clvideostate_t state;
2904 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2906 name = PRVM_G_STRING( OFS_PARM0 );
2907 VM_CheckEmptyString( name );
2909 state = PRVM_G_FLOAT( OFS_PARM1 );
2911 video = CL_GetVideo( name );
2912 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2913 CL_SetVideoState( video, state );
2917 ========================
2920 float cin_getstate(string name)
2921 ========================
2923 void VM_cin_getstate( void )
2928 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2930 name = PRVM_G_STRING( OFS_PARM0 );
2931 VM_CheckEmptyString( name );
2933 video = CL_GetVideo( name );
2935 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2937 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2941 ========================
2944 void cin_restart(string name)
2945 ========================
2947 void VM_cin_restart( void )
2952 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2954 name = PRVM_G_STRING( OFS_PARM0 );
2955 VM_CheckEmptyString( name );
2957 video = CL_GetVideo( name );
2959 CL_RestartVideo( video );
2962 ////////////////////////////////////////
2963 // AltString functions
2964 ////////////////////////////////////////
2967 ========================
2970 float altstr_count(string)
2971 ========================
2973 void VM_altstr_count( void )
2978 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2980 altstr = PRVM_G_STRING( OFS_PARM0 );
2981 //VM_CheckEmptyString( altstr );
2983 for( count = 0, pos = altstr ; *pos ; pos++ )
2984 if( *pos == '\\' && !*++pos )
2986 else if( *pos == '\'' )
2989 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2993 ========================
2996 string altstr_prepare(string)
2997 ========================
2999 void VM_altstr_prepare( void )
3005 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3007 instr = PRVM_G_STRING( OFS_PARM0 );
3008 //VM_CheckEmptyString( instr );
3009 outstr = VM_GetTempString();
3011 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3020 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3024 ========================
3027 string altstr_get(string, float)
3028 ========================
3030 void VM_altstr_get( void )
3032 char *altstr, *pos, *outstr, *out;
3035 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3037 altstr = PRVM_G_STRING( OFS_PARM0 );
3038 //VM_CheckEmptyString( altstr );
3040 count = PRVM_G_FLOAT( OFS_PARM1 );
3041 count = count * 2 + 1;
3043 for( pos = altstr ; *pos && count ; pos++ )
3044 if( *pos == '\\' && !*++pos )
3046 else if( *pos == '\'' )
3050 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3054 outstr = VM_GetTempString();
3055 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3056 if( *pos == '\\' ) {
3061 } else if( *pos == '\'' )
3067 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3071 ========================
3074 string altstr_set(string altstr, float num, string set)
3075 ========================
3077 void VM_altstr_set( void )
3084 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3086 altstr = PRVM_G_STRING( OFS_PARM0 );
3087 //VM_CheckEmptyString( altstr );
3089 num = PRVM_G_FLOAT( OFS_PARM1 );
3091 str = PRVM_G_STRING( OFS_PARM2 );
3092 //VM_CheckEmptyString( str );
3094 outstr = out = VM_GetTempString();
3095 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3096 if( *in == '\\' && !*++in )
3098 else if( *in == '\'' )
3102 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3106 for( ; *str; *out++ = *str++ );
3107 // now jump over the old contents
3109 if( *in == '\'' || (*in == '\\' && !*++in) )
3113 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3118 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3121 void VM_Cmd_Init(void)
3123 // only init the stuff for the current prog
3124 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3129 void VM_Cmd_Reset(void)
3131 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3132 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3133 memheader_t *header;
3136 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3137 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3140 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3141 CL_PurgeOwner( MENUOWNER );
3143 VM_Files_CloseAll();
3146 //============================================================================
3149 char *vm_sv_extensions =
3152 prvm_builtin_t vm_sv_builtins[] = {
3153 0 // to be consistent with the old vm
3156 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3158 void VM_SV_Cmd_Init(void)
3162 void VM_SV_Cmd_Reset(void)
3166 //============================================================================
3169 char *vm_cl_extensions =
3172 prvm_builtin_t vm_cl_builtins[] = {
3173 0 // to be consistent with the old vm
3176 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3178 void VM_CL_Cmd_Init(void)
3182 void VM_CL_Cmd_Reset(void)
3186 //============================================================================
3189 char *vm_m_extensions =
3196 setmousetarget(float target)
3199 void VM_M_setmousetarget(void)
3201 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3203 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3206 in_client_mouse = false;
3209 in_client_mouse = true;
3212 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3220 float getmousetarget
3223 void VM_M_getmousetarget(void)
3225 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3228 PRVM_G_FLOAT(OFS_RETURN) = 2;
3230 PRVM_G_FLOAT(OFS_RETURN) = 1;
3239 setkeydest(float dest)
3242 void VM_M_setkeydest(void)
3244 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3246 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3250 key_dest = key_game;
3254 key_dest = key_menu;
3258 // key_dest = key_message
3261 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3272 void VM_M_getkeydest(void)
3274 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3276 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3280 PRVM_G_FLOAT(OFS_RETURN) = 0;
3283 PRVM_G_FLOAT(OFS_RETURN) = 2;
3287 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3290 PRVM_G_FLOAT(OFS_RETURN) = 3;
3298 callfunction(...,string function_name)
3302 mfunction_t *PRVM_ED_FindFunction (const char *name);
3303 void VM_M_callfunction(void)
3309 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3311 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3314 PRVM_ERROR("VM_M_callfunction: null string !\n");
3316 VM_CheckEmptyString(s);
3318 func = PRVM_ED_FindFunction(s);
3321 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3322 else if (func->first_statement < 0)
3324 // negative statements are built in functions
3325 int builtinnumber = -func->first_statement;
3326 prog->xfunction->builtinsprofile++;
3327 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3328 prog->builtins[builtinnumber]();
3330 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3335 PRVM_ExecuteProgram(func - prog->functions,"");
3344 float isfunction(string function_name)
3347 mfunction_t *PRVM_ED_FindFunction (const char *name);
3348 void VM_M_isfunction(void)
3353 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3355 s = PRVM_G_STRING(OFS_PARM0);
3358 PRVM_ERROR("VM_M_isfunction: null string !\n");
3360 VM_CheckEmptyString(s);
3362 func = PRVM_ED_FindFunction(s);
3365 PRVM_G_FLOAT(OFS_RETURN) = false;
3367 PRVM_G_FLOAT(OFS_RETURN) = true;
3374 writetofile(float fhandle, entity ent)
3377 void VM_M_writetofile(void)
3382 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3384 filenum = PRVM_G_FLOAT(OFS_PARM0);
3385 if (filenum < 0 || filenum >= MAX_VMFILES)
3387 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3390 if (VM_FILES[filenum] == NULL)
3392 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3396 ent = PRVM_G_EDICT(OFS_PARM1);
3399 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3403 PRVM_ED_Write (VM_FILES[filenum], ent);
3410 vector getresolution(float number)
3413 extern unsigned short video_resolutions[][2];
3414 void VM_M_getresolution(void)
3417 VM_SAFEPARMCOUNT(1, VM_getresolution);
3419 nr = PRVM_G_FLOAT(OFS_PARM0);
3422 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3423 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3424 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3431 string keynumtostring(float keynum)
3434 void VM_M_keynumtostring(void)
3438 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3440 keynum = PRVM_G_FLOAT(OFS_PARM0);
3442 tmp = VM_GetTempString();
3444 strcpy(tmp, Key_KeynumToString(keynum));
3446 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3453 float stringtokeynum(string key)
3456 void VM_M_stringtokeynum( void )
3459 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3461 str = PRVM_G_STRING( OFS_PARM0 );
3463 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3468 VM_M_findkeysforcommand
3470 string findkeysforcommand(string command)
3472 the returned string is an altstring
3475 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3477 void M_FindKeysForCommand(char *command, int *keys);
3478 void VM_M_findkeysforcommand(void)
3484 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3486 cmd = PRVM_G_STRING(OFS_PARM0);
3488 VM_CheckEmptyString(cmd);
3490 (ret = VM_GetTempString())[0] = 0;
3492 M_FindKeysForCommand(cmd, keys);
3494 for(i = 0; i < NUMKEYS; i++)
3495 ret = strcat(ret, va(" \'%i\'", keys[i]));
3497 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3502 VM_M_gethostcachestat
3504 float gethostcachestat(float type)
3509 0 hostcache_viewcount
3510 1 hostcache_totalcount
3518 void VM_M_gethostcachestat( void )
3521 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachestat );
3523 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3525 type = PRVM_G_FLOAT( OFS_PARM0 );
3529 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_viewcount;
3532 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_cachecount;
3534 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3537 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3540 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3543 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3546 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortbyfield;
3549 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortdescending;
3552 Con_Printf( "VM_M_gethostcachestat: bad type %i!\n", type );
3557 ========================
3558 VM_M_resethostcachemasks
3560 resethostcachemasks()
3561 ========================
3563 void VM_M_resethostcachemasks( void )
3565 HostCache_ResetMasks();
3570 ========================
3571 VM_M_sethostcachemaskstring
3573 sethostcachemaskstring(float mask, float fld, string str, float op)
3576 ========================
3578 void VM_M_sethostcachemaskstring( void )
3582 hostcache_mask_t *mask;
3585 VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemaskstring );
3586 str = PRVM_G_STRING( OFS_PARM1 );
3588 PRVM_ERROR( "VM_M_sethostcachemaskstring: null string passed!" );
3590 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3591 if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
3592 mask = &hostcache_andmasks[masknr];
3593 else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
3594 mask = &hostcache_ormasks[masknr - 512 ];
3596 Con_Printf( "VM_M_sethostcachemaskstring: invalid mask number %i\n", masknr );
3600 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3604 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3607 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3610 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3613 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3616 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3619 Con_Printf( "VM_M_sethostcachemaskstring: Bad field number %i passed!\n", field );
3623 mask->active = true;
3624 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3628 ========================
3629 VM_M_sethostcachemasknumber
3631 sethostcachemasknumber(float mask, float fld, float num, float op)
3635 ========================
3637 void VM_M_sethostcachemasknumber( void )
3640 hostcache_mask_t *mask;
3643 VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemasknumber );
3645 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3646 if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
3647 mask = &hostcache_andmasks[masknr];
3648 else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
3649 mask = &hostcache_ormasks[masknr - 512 ];
3651 Con_Printf( "VM_M_sethostcachemasknumber: invalid mask number %i\n", masknr );
3655 number = PRVM_G_FLOAT( OFS_PARM2 );
3656 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3659 case HCIF_MAXPLAYERS:
3660 mask->info.maxplayers = number;
3662 case HCIF_NUMPLAYERS:
3663 mask->info.numplayers = number;
3666 mask->info.ping = number;
3669 mask->info.protocol = number;
3672 Con_Printf( "VM_M_sethostcachemasknumber: Bad field number %i passed!\n", field );
3676 mask->active = true;
3677 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3682 ========================
3683 VM_M_resorthostcache
3686 ========================
3688 void VM_M_resorthostcache( void )
3690 HostCache_RebuildViewSet();
3695 VM_M_gethostcachestring
3697 string gethostcachestring(float field, float hostnr)
3700 void VM_M_gethostcachestring(void)
3705 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3707 PRVM_G_INT(OFS_RETURN) = 0;
3709 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3711 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3713 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3716 cache = hostcache_viewset[hostnr];
3717 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3719 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3722 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3725 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3728 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3731 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3733 // TODO remove this again
3735 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3738 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3741 Con_Print("VM_M_gethostcachestring: bad field number passed!\n");
3747 VM_M_gethostcachenumber
3749 float gethostcachenumber(float field, float hostnr)
3752 void VM_M_gethostcachenumber(void)
3757 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3759 PRVM_G_INT(OFS_RETURN) = 0;
3761 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3763 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3765 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3768 cache = hostcache_viewset[hostnr];
3769 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3770 case HCIF_MAXPLAYERS:
3771 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3773 case HCIF_NUMPLAYERS:
3774 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3777 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3780 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3783 Con_Print("VM_M_gethostcachenumber: bad field number passed!\n");
3788 ========================
3789 VM_M_sethostcachesort
3791 sethostcachesort(float field, float descending)
3792 ========================
3794 void VM_M_sethostcachesort( void )
3796 VM_SAFEPARMCOUNT( 2, VM_M_sethostcachesort );
3798 hostcache_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3799 hostcache_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3803 ========================
3804 VM_M_refreshhostcache
3807 ========================
3809 void VM_M_refreshhostcache( void )
3811 VM_SAFEPARMCOUNT( 0, VM_M_refreshhostcache );
3812 HostCache_QueryList();
3816 ========================
3817 VM_M_gethostcacheindexforkey
3819 float gethostcacheindexforkey(string key)
3820 ========================
3822 void VM_M_gethostcacheindexforkey( void )
3825 VM_SAFEPARMCOUNT( 1, VM_M_gethostcacheindexforkey );
3827 key = PRVM_G_STRING( OFS_PARM0 );
3828 VM_CheckEmptyString( key );
3830 if( !strcmp( key, "cname" ) )
3831 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_CNAME;
3832 else if( !strcmp( key, "ping" ) )
3833 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PING;
3834 else if( !strcmp( key, "game" ) )
3835 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_GAME;
3836 else if( !strcmp( key, "mod" ) )
3837 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MOD;
3838 else if( !strcmp( key, "map" ) )
3839 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAP;
3840 else if( !strcmp( key, "name" ) )
3841 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NAME;
3842 else if( !strcmp( key, "maxplayers" ) )
3843 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAXPLAYERS;
3844 else if( !strcmp( key, "numplayers" ) )
3845 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NUMPLAYERS;
3846 else if( !strcmp( key, "protocol" ) )
3847 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PROTOCOL;
3849 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3853 ========================
3854 VM_M_addwantedhostcachekey
3856 addwantedhostcachekey(string key)
3857 ========================
3859 void VM_M_addwantedhostcachekey( void )
3861 VM_SAFEPARMCOUNT( 1, VM_M_addwantedhostcachekey );
3864 prvm_builtin_t vm_m_builtins[] = {
3865 0, // to be consistent with the old vm
3866 // common builtings (mostly)
3943 VM_search_getfilename, // 77
3947 VM_itof, // isString
3951 VM_altstr_set, // 85
3965 VM_WriteEntity, // 408
3981 VM_drawresetcliparea,
3982 VM_getimagesize,// 460
3987 VM_cin_restart, // 465
3996 VM_M_setmousetarget,
3997 VM_M_getmousetarget,
4002 VM_M_keynumtostring,
4003 VM_M_findkeysforcommand,// 610
4004 VM_M_gethostcachestat,
4005 VM_M_gethostcachestring,
4006 VM_M_parseentitydata,
4007 VM_M_stringtokeynum,
4008 VM_M_resethostcachemasks,
4009 VM_M_sethostcachemaskstring,
4010 VM_M_sethostcachemasknumber,
4011 VM_M_resorthostcache,
4012 VM_M_sethostcachesort,
4013 VM_M_refreshhostcache,
4014 VM_M_gethostcachenumber,
4015 VM_M_gethostcacheindexforkey,
4016 VM_M_addwantedhostcachekey // 623
4019 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4021 void VM_M_Cmd_Init(void)
4026 void VM_M_Cmd_Reset(void)