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
1857 c = FS_Getc(VM_FILES[filenum]);
1859 FS_UnGetc(VM_FILES[filenum], (unsigned char)c);
1861 if (developer.integer >= 3)
1862 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1864 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1866 PRVM_G_INT(OFS_RETURN) = 0;
1873 fputs(float fhandle, string s)
1876 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1880 char string[VM_STRINGTEMP_LENGTH];
1883 VM_SAFEPARMCOUNT(2,VM_fputs);
1885 filenum = PRVM_G_FLOAT(OFS_PARM0);
1886 if (filenum < 0 || filenum >= MAX_VMFILES)
1888 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1891 if (VM_FILES[filenum] == NULL)
1893 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1896 VM_VarString(1, string, sizeof(string));
1897 if ((stringlength = strlen(string)))
1898 FS_Write(VM_FILES[filenum], string, stringlength);
1899 if (developer.integer)
1900 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1907 float strlen(string s)
1910 //float(string s) strlen = #114; // returns how many characters are in a string
1911 void VM_strlen(void)
1915 VM_SAFEPARMCOUNT(1,VM_strlen);
1917 s = PRVM_G_STRING(OFS_PARM0);
1919 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1921 PRVM_G_FLOAT(OFS_RETURN) = 0;
1928 string strcat(string,string,...[string])
1931 //string(string s1, string s2) strcat = #115;
1932 // concatenates two strings (for example "abc", "def" would return "abcdef")
1933 // and returns as a tempstring
1934 void VM_strcat(void)
1939 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1941 s = VM_GetTempString();
1942 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1943 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1950 string substring(string s, float start, float length)
1953 // string(string s, float start, float length) substring = #116;
1954 // returns a section of a string as a tempstring
1955 void VM_substring(void)
1957 int i, start, length;
1960 VM_SAFEPARMCOUNT(3,VM_substring);
1962 string = VM_GetTempString();
1963 s = PRVM_G_STRING(OFS_PARM0);
1964 start = PRVM_G_FLOAT(OFS_PARM1);
1965 length = PRVM_G_FLOAT(OFS_PARM2);
1968 for (i = 0;i < start && *s;i++, s++);
1969 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1972 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1979 vector stov(string s)
1982 //vector(string s) stov = #117; // returns vector value from a string
1985 char string[VM_STRINGTEMP_LENGTH];
1987 VM_SAFEPARMCOUNT(1,VM_stov);
1989 VM_VarString(0, string, sizeof(string));
1990 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1997 string strzone(string s)
2000 //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)
2001 void VM_strzone(void)
2005 VM_SAFEPARMCOUNT(1,VM_strzone);
2007 in = PRVM_G_STRING(OFS_PARM0);
2008 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
2010 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2020 //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!!!)
2021 void VM_strunzone(void)
2024 VM_SAFEPARMCOUNT(1,VM_strunzone);
2026 str = PRVM_G_STRING(OFS_PARM0);
2027 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2028 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2035 VM_command (used by client and menu)
2037 clientcommand(float client, string s) (for client and menu)
2040 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2041 //this function originally written by KrimZon, made shorter by LordHavoc
2042 void VM_clcommand (void)
2044 client_t *temp_client;
2047 VM_SAFEPARMCOUNT(2,VM_clcommand);
2049 i = PRVM_G_FLOAT(OFS_PARM0);
2050 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2052 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2056 temp_client = host_client;
2057 host_client = svs.clients + i;
2058 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2059 host_client = temp_client;
2067 float tokenize(string s)
2070 //float(string s) tokenize = #441;
2071 // takes apart a string into individal words (access them with argv), returns how many
2072 // this function originally written by KrimZon, made shorter by LordHavoc
2073 static char **tokens = NULL;
2074 static int max_tokens, num_tokens = 0;
2075 void VM_tokenize (void)
2080 VM_SAFEPARMCOUNT(1,VM_tokenize);
2082 str = PRVM_G_STRING(OFS_PARM0);
2087 for (i=0;i<num_tokens;i++)
2093 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2094 max_tokens = strlen(str);
2096 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2098 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2099 strcpy(tokens[num_tokens], com_token);
2102 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2109 string argv(float n)
2112 //string(float n) argv = #442;
2113 // returns a word from the tokenized string (returns nothing for an invalid index)
2114 // this function originally written by KrimZon, made shorter by LordHavoc
2119 VM_SAFEPARMCOUNT(1,VM_argv);
2121 token_num = PRVM_G_FLOAT(OFS_PARM0);
2122 if (token_num >= 0 && token_num < num_tokens)
2123 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2125 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2129 //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)
2130 void PF_setattachment (void)
2132 edict_t *e = G_EDICT(OFS_PARM0);
2133 edict_t *tagentity = G_EDICT(OFS_PARM1);
2134 char *tagname = G_STRING(OFS_PARM2);
2139 if (tagentity == NULL)
2140 tagentity = sv.edicts;
2142 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2144 v->edict = EDICT_TO_PROG(tagentity);
2146 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2149 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2151 modelindex = (int)tagentity->v->modelindex;
2152 if (modelindex >= 0 && modelindex < MAX_MODELS)
2154 model = sv.models[modelindex];
2155 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2156 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2157 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2159 // FIXME: use a model function to get tag info (need to handle skeletal)
2160 if (v->_float == 0 && model->alias.aliasnum_tags)
2161 for (i = 0;i < model->alias.aliasnum_tags;i++)
2162 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2165 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);
2168 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));
2179 void VM_isserver(void)
2181 VM_SAFEPARMCOUNT(0,VM_serverstate);
2183 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2193 void VM_clientcount(void)
2195 VM_SAFEPARMCOUNT(0,VM_clientcount);
2197 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2207 void VM_clientstate(void)
2209 VM_SAFEPARMCOUNT(0,VM_clientstate);
2211 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2218 float getostype(void)
2220 */ // not used at the moment -> not included in the common list
2221 void VM_getostype(void)
2223 VM_SAFEPARMCOUNT(0,VM_getostype);
2228 OS_MAC - not supported
2232 PRVM_G_FLOAT(OFS_RETURN) = 0;
2234 PRVM_G_FLOAT(OFS_RETURN) = 2;
2236 PRVM_G_FLOAT(OFS_RETURN) = 1;
2244 vector getmousepos()
2247 void VM_getmousepos(void)
2250 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2252 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2253 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2254 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2264 void VM_gettime(void)
2266 VM_SAFEPARMCOUNT(0,VM_gettime);
2268 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2275 loadfromdata(string data)
2278 void VM_loadfromdata(void)
2280 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2282 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2286 ========================
2287 VM_M_parseentitydata
2289 parseentitydata(entity ent, string data)
2290 ========================
2292 void VM_M_parseentitydata(void)
2297 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2299 // get edict and test it
2300 ent = PRVM_G_EDICT(OFS_PARM0);
2302 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2304 data = PRVM_G_STRING(OFS_PARM1);
2306 // parse the opening brace
2307 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2308 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2310 PRVM_ED_ParseEdict (data, ent);
2317 loadfromfile(string file)
2320 void VM_loadfromfile(void)
2325 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2327 filename = PRVM_G_STRING(OFS_PARM0);
2328 // .. is parent directory on many platforms
2329 // / is parent directory on Amiga
2330 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2331 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2332 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2334 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2335 PRVM_G_FLOAT(OFS_RETURN) = -4;
2339 // not conform with VM_fopen
2340 data = FS_LoadFile(filename, tempmempool, false);
2342 PRVM_G_FLOAT(OFS_RETURN) = -1;
2344 PRVM_ED_LoadFromFile(data);
2355 float mod(float val, float m)
2358 void VM_modulo(void)
2361 VM_SAFEPARMCOUNT(2,VM_module);
2363 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2364 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2366 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2369 void VM_Search_Init(void)
2371 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2374 void VM_Search_Reset(void)
2377 // reset the fssearch list
2378 for(i = 0; i < MAX_VMSEARCHES; i++)
2379 if(VM_SEARCHLIST[i])
2380 FS_FreeSearch(VM_SEARCHLIST[i]);
2381 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2388 float search_begin(string pattern, float caseinsensitive, float quiet)
2391 void VM_search_begin(void)
2395 int caseinsens, quiet;
2397 VM_SAFEPARMCOUNT(3, VM_search_begin);
2399 pattern = PRVM_G_STRING(OFS_PARM0);
2401 VM_CheckEmptyString(pattern);
2403 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2404 quiet = PRVM_G_FLOAT(OFS_PARM2);
2406 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2407 if(!VM_SEARCHLIST[handle])
2410 if(handle >= MAX_VMSEARCHES)
2412 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2413 PRVM_G_FLOAT(OFS_RETURN) = -2;
2417 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2418 PRVM_G_FLOAT(OFS_RETURN) = -1;
2420 PRVM_G_FLOAT(OFS_RETURN) = handle;
2427 void search_end(float handle)
2430 void VM_search_end(void)
2433 VM_SAFEPARMCOUNT(1, VM_search_end);
2435 handle = PRVM_G_FLOAT(OFS_PARM0);
2437 if(handle < 0 || handle >= MAX_VMSEARCHES)
2439 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2442 if(VM_SEARCHLIST[handle] == NULL)
2444 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2448 FS_FreeSearch(VM_SEARCHLIST[handle]);
2449 VM_SEARCHLIST[handle] = NULL;
2456 float search_getsize(float handle)
2459 void VM_search_getsize(void)
2462 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2464 handle = PRVM_G_FLOAT(OFS_PARM0);
2466 if(handle < 0 || handle >= MAX_VMSEARCHES)
2468 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2471 if(VM_SEARCHLIST[handle] == NULL)
2473 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2477 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2482 VM_search_getfilename
2484 string search_getfilename(float handle, float num)
2487 void VM_search_getfilename(void)
2489 int handle, filenum;
2491 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2493 handle = PRVM_G_FLOAT(OFS_PARM0);
2494 filenum = PRVM_G_FLOAT(OFS_PARM1);
2496 if(handle < 0 || handle >= MAX_VMSEARCHES)
2498 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2501 if(VM_SEARCHLIST[handle] == NULL)
2503 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2506 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2508 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2512 tmp = VM_GetTempString();
2513 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2515 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2522 string chr(float ascii)
2528 VM_SAFEPARMCOUNT(1, VM_chr);
2530 tmp = VM_GetTempString();
2531 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2534 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2537 //=============================================================================
2538 // Draw builtins (client & menu)
2544 float iscachedpic(string pic)
2547 void VM_iscachedpic(void)
2549 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2551 // drawq hasnt such a function, thus always return true
2552 PRVM_G_FLOAT(OFS_RETURN) = false;
2559 string precache_pic(string pic)
2562 void VM_precache_pic(void)
2566 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2568 s = PRVM_G_STRING(OFS_PARM0);
2569 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2572 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2574 VM_CheckEmptyString (s);
2576 if(!Draw_CachePic(s))
2577 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2587 void VM_freepic(void)
2591 VM_SAFEPARMCOUNT(1,VM_freepic);
2593 s = PRVM_G_STRING(OFS_PARM0);
2596 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2598 VM_CheckEmptyString (s);
2607 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2610 void VM_drawcharacter(void)
2612 float *pos,*scale,*rgb;
2615 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2617 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2620 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2621 PRVM_G_FLOAT(OFS_RETURN) = -1;
2625 pos = PRVM_G_VECTOR(OFS_PARM0);
2626 scale = PRVM_G_VECTOR(OFS_PARM2);
2627 rgb = PRVM_G_VECTOR(OFS_PARM3);
2628 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2630 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2632 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2633 PRVM_G_FLOAT(OFS_RETURN) = -2;
2637 if(pos[2] || scale[2])
2638 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")));
2640 if(!scale[0] || !scale[1])
2642 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2643 PRVM_G_FLOAT(OFS_RETURN) = -3;
2647 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2648 PRVM_G_FLOAT(OFS_RETURN) = 1;
2655 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2658 void VM_drawstring(void)
2660 float *pos,*scale,*rgb;
2663 VM_SAFEPARMCOUNT(6,VM_drawstring);
2665 string = PRVM_G_STRING(OFS_PARM1);
2668 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2669 PRVM_G_FLOAT(OFS_RETURN) = -1;
2673 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2675 pos = PRVM_G_VECTOR(OFS_PARM0);
2676 scale = PRVM_G_VECTOR(OFS_PARM2);
2677 rgb = PRVM_G_VECTOR(OFS_PARM3);
2678 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2680 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2682 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2683 PRVM_G_FLOAT(OFS_RETURN) = -2;
2687 if(!scale[0] || !scale[1])
2689 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2690 PRVM_G_FLOAT(OFS_RETURN) = -3;
2694 if(pos[2] || scale[2])
2695 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")));
2697 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2698 PRVM_G_FLOAT(OFS_RETURN) = 1;
2704 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2707 void VM_drawpic(void)
2710 float *size, *pos, *rgb;
2713 VM_SAFEPARMCOUNT(6,VM_drawpic);
2715 pic = PRVM_G_STRING(OFS_PARM1);
2719 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2720 PRVM_G_FLOAT(OFS_RETURN) = -1;
2724 VM_CheckEmptyString (pic);
2726 // is pic cached ? no function yet for that
2729 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2730 PRVM_G_FLOAT(OFS_RETURN) = -4;
2734 pos = PRVM_G_VECTOR(OFS_PARM0);
2735 size = PRVM_G_VECTOR(OFS_PARM2);
2736 rgb = PRVM_G_VECTOR(OFS_PARM3);
2737 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2739 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2741 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2742 PRVM_G_FLOAT(OFS_RETURN) = -2;
2746 if(pos[2] || size[2])
2747 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")));
2749 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2750 PRVM_G_FLOAT(OFS_RETURN) = 1;
2757 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2760 void VM_drawfill(void)
2762 float *size, *pos, *rgb;
2765 VM_SAFEPARMCOUNT(5,VM_drawfill);
2768 pos = PRVM_G_VECTOR(OFS_PARM0);
2769 size = PRVM_G_VECTOR(OFS_PARM1);
2770 rgb = PRVM_G_VECTOR(OFS_PARM2);
2771 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2773 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2775 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2776 PRVM_G_FLOAT(OFS_RETURN) = -2;
2780 if(pos[2] || size[2])
2781 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")));
2783 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2784 PRVM_G_FLOAT(OFS_RETURN) = 1;
2791 drawsetcliparea(float x, float y, float width, float height)
2794 void VM_drawsetcliparea(void)
2797 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2799 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2800 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2801 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2802 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2804 DrawQ_SetClipArea(x, y, w, h);
2809 VM_drawresetcliparea
2814 void VM_drawresetcliparea(void)
2816 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2818 DrawQ_ResetClipArea();
2825 vector getimagesize(string pic)
2828 void VM_getimagesize(void)
2833 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2835 p = PRVM_G_STRING(OFS_PARM0);
2838 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2840 VM_CheckEmptyString (p);
2842 pic = Draw_CachePic (p);
2844 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2845 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2846 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2849 // CL_Video interface functions
2852 ========================
2855 float cin_open(string file, string name)
2856 ========================
2858 void VM_cin_open( void )
2863 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2865 file = PRVM_G_STRING( OFS_PARM0 );
2866 name = PRVM_G_STRING( OFS_PARM1 );
2868 VM_CheckEmptyString( file );
2869 VM_CheckEmptyString( name );
2871 if( CL_OpenVideo( file, name, MENUOWNER ) )
2872 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2874 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2878 ========================
2881 void cin_close(string name)
2882 ========================
2884 void VM_cin_close( void )
2888 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2890 name = PRVM_G_STRING( OFS_PARM0 );
2891 VM_CheckEmptyString( name );
2893 CL_CloseVideo( CL_GetVideo( name ) );
2897 ========================
2899 void cin_setstate(string name, float type)
2900 ========================
2902 void VM_cin_setstate( void )
2905 clvideostate_t state;
2908 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2910 name = PRVM_G_STRING( OFS_PARM0 );
2911 VM_CheckEmptyString( name );
2913 state = PRVM_G_FLOAT( OFS_PARM1 );
2915 video = CL_GetVideo( name );
2916 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2917 CL_SetVideoState( video, state );
2921 ========================
2924 float cin_getstate(string name)
2925 ========================
2927 void VM_cin_getstate( void )
2932 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2934 name = PRVM_G_STRING( OFS_PARM0 );
2935 VM_CheckEmptyString( name );
2937 video = CL_GetVideo( name );
2939 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2941 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2945 ========================
2948 void cin_restart(string name)
2949 ========================
2951 void VM_cin_restart( void )
2956 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2958 name = PRVM_G_STRING( OFS_PARM0 );
2959 VM_CheckEmptyString( name );
2961 video = CL_GetVideo( name );
2963 CL_RestartVideo( video );
2966 ////////////////////////////////////////
2967 // AltString functions
2968 ////////////////////////////////////////
2971 ========================
2974 float altstr_count(string)
2975 ========================
2977 void VM_altstr_count( void )
2982 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2984 altstr = PRVM_G_STRING( OFS_PARM0 );
2985 //VM_CheckEmptyString( altstr );
2987 for( count = 0, pos = altstr ; *pos ; pos++ )
2988 if( *pos == '\\' && !*++pos )
2990 else if( *pos == '\'' )
2993 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2997 ========================
3000 string altstr_prepare(string)
3001 ========================
3003 void VM_altstr_prepare( void )
3009 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3011 instr = PRVM_G_STRING( OFS_PARM0 );
3012 //VM_CheckEmptyString( instr );
3013 outstr = VM_GetTempString();
3015 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3024 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3028 ========================
3031 string altstr_get(string, float)
3032 ========================
3034 void VM_altstr_get( void )
3036 char *altstr, *pos, *outstr, *out;
3039 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3041 altstr = PRVM_G_STRING( OFS_PARM0 );
3042 //VM_CheckEmptyString( altstr );
3044 count = PRVM_G_FLOAT( OFS_PARM1 );
3045 count = count * 2 + 1;
3047 for( pos = altstr ; *pos && count ; pos++ )
3048 if( *pos == '\\' && !*++pos )
3050 else if( *pos == '\'' )
3054 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3058 outstr = VM_GetTempString();
3059 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3060 if( *pos == '\\' ) {
3065 } else if( *pos == '\'' )
3071 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3075 ========================
3078 string altstr_set(string altstr, float num, string set)
3079 ========================
3081 void VM_altstr_set( void )
3088 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3090 altstr = PRVM_G_STRING( OFS_PARM0 );
3091 //VM_CheckEmptyString( altstr );
3093 num = PRVM_G_FLOAT( OFS_PARM1 );
3095 str = PRVM_G_STRING( OFS_PARM2 );
3096 //VM_CheckEmptyString( str );
3098 outstr = out = VM_GetTempString();
3099 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3100 if( *in == '\\' && !*++in )
3102 else if( *in == '\'' )
3106 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3110 for( ; *str; *out++ = *str++ );
3111 // now jump over the old contents
3113 if( *in == '\'' || (*in == '\\' && !*++in) )
3117 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3122 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3125 void VM_Cmd_Init(void)
3127 // only init the stuff for the current prog
3128 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3133 void VM_Cmd_Reset(void)
3135 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3136 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3137 memheader_t *header;
3140 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3141 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3144 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3145 CL_PurgeOwner( MENUOWNER );
3147 VM_Files_CloseAll();
3150 //============================================================================
3153 char *vm_sv_extensions =
3156 prvm_builtin_t vm_sv_builtins[] = {
3157 0 // to be consistent with the old vm
3160 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3162 void VM_SV_Cmd_Init(void)
3166 void VM_SV_Cmd_Reset(void)
3170 //============================================================================
3173 char *vm_cl_extensions =
3176 prvm_builtin_t vm_cl_builtins[] = {
3177 0 // to be consistent with the old vm
3180 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3182 void VM_CL_Cmd_Init(void)
3186 void VM_CL_Cmd_Reset(void)
3190 //============================================================================
3193 char *vm_m_extensions =
3200 setmousetarget(float target)
3203 void VM_M_setmousetarget(void)
3205 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3207 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3210 in_client_mouse = false;
3213 in_client_mouse = true;
3216 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3224 float getmousetarget
3227 void VM_M_getmousetarget(void)
3229 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3232 PRVM_G_FLOAT(OFS_RETURN) = 2;
3234 PRVM_G_FLOAT(OFS_RETURN) = 1;
3243 setkeydest(float dest)
3246 void VM_M_setkeydest(void)
3248 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3250 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3254 key_dest = key_game;
3258 key_dest = key_menu;
3262 // key_dest = key_message
3265 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3276 void VM_M_getkeydest(void)
3278 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3280 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3284 PRVM_G_FLOAT(OFS_RETURN) = 0;
3287 PRVM_G_FLOAT(OFS_RETURN) = 2;
3291 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3294 PRVM_G_FLOAT(OFS_RETURN) = 3;
3302 callfunction(...,string function_name)
3306 mfunction_t *PRVM_ED_FindFunction (const char *name);
3307 void VM_M_callfunction(void)
3313 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3315 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3318 PRVM_ERROR("VM_M_callfunction: null string !\n");
3320 VM_CheckEmptyString(s);
3322 func = PRVM_ED_FindFunction(s);
3325 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3326 else if (func->first_statement < 0)
3328 // negative statements are built in functions
3329 int builtinnumber = -func->first_statement;
3330 prog->xfunction->builtinsprofile++;
3331 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3332 prog->builtins[builtinnumber]();
3334 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3339 PRVM_ExecuteProgram(func - prog->functions,"");
3348 float isfunction(string function_name)
3351 mfunction_t *PRVM_ED_FindFunction (const char *name);
3352 void VM_M_isfunction(void)
3357 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3359 s = PRVM_G_STRING(OFS_PARM0);
3362 PRVM_ERROR("VM_M_isfunction: null string !\n");
3364 VM_CheckEmptyString(s);
3366 func = PRVM_ED_FindFunction(s);
3369 PRVM_G_FLOAT(OFS_RETURN) = false;
3371 PRVM_G_FLOAT(OFS_RETURN) = true;
3378 writetofile(float fhandle, entity ent)
3381 void VM_M_writetofile(void)
3386 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3388 filenum = PRVM_G_FLOAT(OFS_PARM0);
3389 if (filenum < 0 || filenum >= MAX_VMFILES)
3391 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3394 if (VM_FILES[filenum] == NULL)
3396 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3400 ent = PRVM_G_EDICT(OFS_PARM1);
3403 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3407 PRVM_ED_Write (VM_FILES[filenum], ent);
3414 vector getresolution(float number)
3417 extern unsigned short video_resolutions[][2];
3418 void VM_M_getresolution(void)
3421 VM_SAFEPARMCOUNT(1, VM_getresolution);
3423 nr = PRVM_G_FLOAT(OFS_PARM0);
3426 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3427 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3428 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3435 string keynumtostring(float keynum)
3438 void VM_M_keynumtostring(void)
3442 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3444 keynum = PRVM_G_FLOAT(OFS_PARM0);
3446 tmp = VM_GetTempString();
3448 strcpy(tmp, Key_KeynumToString(keynum));
3450 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3457 float stringtokeynum(string key)
3460 void VM_M_stringtokeynum( void )
3463 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3465 str = PRVM_G_STRING( OFS_PARM0 );
3467 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3472 VM_M_findkeysforcommand
3474 string findkeysforcommand(string command)
3476 the returned string is an altstring
3479 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3481 void M_FindKeysForCommand(char *command, int *keys);
3482 void VM_M_findkeysforcommand(void)
3488 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3490 cmd = PRVM_G_STRING(OFS_PARM0);
3492 VM_CheckEmptyString(cmd);
3494 (ret = VM_GetTempString())[0] = 0;
3496 M_FindKeysForCommand(cmd, keys);
3498 for(i = 0; i < NUMKEYS; i++)
3499 ret = strcat(ret, va(" \'%i\'", keys[i]));
3501 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3506 VM_M_gethostcachestat
3508 float gethostcachestat(float type)
3513 0 hostcache_viewcount
3514 1 hostcache_totalcount
3522 void VM_M_gethostcachestat( void )
3525 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachestat );
3527 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3529 type = PRVM_G_FLOAT( OFS_PARM0 );
3533 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_viewcount;
3536 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_cachecount;
3538 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3541 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3544 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3547 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3550 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortbyfield;
3553 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortdescending;
3556 Con_Printf( "VM_M_gethostcachestat: bad type %i!\n", type );
3561 ========================
3562 VM_M_resethostcachemasks
3564 resethostcachemasks()
3565 ========================
3567 void VM_M_resethostcachemasks( void )
3569 HostCache_ResetMasks();
3574 ========================
3575 VM_M_sethostcachemaskstring
3577 sethostcachemaskstring(float mask, float fld, string str, float op)
3580 ========================
3582 void VM_M_sethostcachemaskstring( void )
3586 hostcache_mask_t *mask;
3589 VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemaskstring );
3590 str = PRVM_G_STRING( OFS_PARM1 );
3592 PRVM_ERROR( "VM_M_sethostcachemaskstring: null string passed!" );
3594 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3595 if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
3596 mask = &hostcache_andmasks[masknr];
3597 else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
3598 mask = &hostcache_ormasks[masknr - 512 ];
3600 Con_Printf( "VM_M_sethostcachemaskstring: invalid mask number %i\n", masknr );
3604 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3608 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3611 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3614 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3617 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3620 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3623 Con_Printf( "VM_M_sethostcachemaskstring: Bad field number %i passed!\n", field );
3627 mask->active = true;
3628 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3632 ========================
3633 VM_M_sethostcachemasknumber
3635 sethostcachemasknumber(float mask, float fld, float num, float op)
3639 ========================
3641 void VM_M_sethostcachemasknumber( void )
3644 hostcache_mask_t *mask;
3647 VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemasknumber );
3649 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3650 if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
3651 mask = &hostcache_andmasks[masknr];
3652 else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
3653 mask = &hostcache_ormasks[masknr - 512 ];
3655 Con_Printf( "VM_M_sethostcachemasknumber: invalid mask number %i\n", masknr );
3659 number = PRVM_G_FLOAT( OFS_PARM2 );
3660 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3663 case HCIF_MAXPLAYERS:
3664 mask->info.maxplayers = number;
3666 case HCIF_NUMPLAYERS:
3667 mask->info.numplayers = number;
3670 mask->info.ping = number;
3673 mask->info.protocol = number;
3676 Con_Printf( "VM_M_sethostcachemasknumber: Bad field number %i passed!\n", field );
3680 mask->active = true;
3681 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3686 ========================
3687 VM_M_resorthostcache
3690 ========================
3692 void VM_M_resorthostcache( void )
3694 HostCache_RebuildViewSet();
3699 VM_M_gethostcachestring
3701 string gethostcachestring(float field, float hostnr)
3704 void VM_M_gethostcachestring(void)
3709 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3711 PRVM_G_INT(OFS_RETURN) = 0;
3713 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3715 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3717 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3720 cache = hostcache_viewset[hostnr];
3721 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3723 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3726 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3729 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3732 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3735 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3737 // TODO remove this again
3739 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3742 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3745 Con_Print("VM_M_gethostcachestring: bad field number passed!\n");
3751 VM_M_gethostcachenumber
3753 float gethostcachenumber(float field, float hostnr)
3756 void VM_M_gethostcachenumber(void)
3761 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3763 PRVM_G_INT(OFS_RETURN) = 0;
3765 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3767 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3769 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3772 cache = hostcache_viewset[hostnr];
3773 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3774 case HCIF_MAXPLAYERS:
3775 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3777 case HCIF_NUMPLAYERS:
3778 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3781 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3784 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3787 Con_Print("VM_M_gethostcachenumber: bad field number passed!\n");
3792 ========================
3793 VM_M_sethostcachesort
3795 sethostcachesort(float field, float descending)
3796 ========================
3798 void VM_M_sethostcachesort( void )
3800 VM_SAFEPARMCOUNT( 2, VM_M_sethostcachesort );
3802 hostcache_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3803 hostcache_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3807 ========================
3808 VM_M_refreshhostcache
3811 ========================
3813 void VM_M_refreshhostcache( void )
3815 VM_SAFEPARMCOUNT( 0, VM_M_refreshhostcache );
3816 HostCache_QueryList();
3820 ========================
3821 VM_M_gethostcacheindexforkey
3823 float gethostcacheindexforkey(string key)
3824 ========================
3826 void VM_M_gethostcacheindexforkey( void )
3829 VM_SAFEPARMCOUNT( 1, VM_M_gethostcacheindexforkey );
3831 key = PRVM_G_STRING( OFS_PARM0 );
3832 VM_CheckEmptyString( key );
3834 if( !strcmp( key, "cname" ) )
3835 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_CNAME;
3836 else if( !strcmp( key, "ping" ) )
3837 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PING;
3838 else if( !strcmp( key, "game" ) )
3839 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_GAME;
3840 else if( !strcmp( key, "mod" ) )
3841 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MOD;
3842 else if( !strcmp( key, "map" ) )
3843 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAP;
3844 else if( !strcmp( key, "name" ) )
3845 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NAME;
3846 else if( !strcmp( key, "maxplayers" ) )
3847 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAXPLAYERS;
3848 else if( !strcmp( key, "numplayers" ) )
3849 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NUMPLAYERS;
3850 else if( !strcmp( key, "protocol" ) )
3851 PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PROTOCOL;
3853 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3857 ========================
3858 VM_M_addwantedhostcachekey
3860 addwantedhostcachekey(string key)
3861 ========================
3863 void VM_M_addwantedhostcachekey( void )
3865 VM_SAFEPARMCOUNT( 1, VM_M_addwantedhostcachekey );
3868 prvm_builtin_t vm_m_builtins[] = {
3869 0, // to be consistent with the old vm
3870 // common builtings (mostly)
3947 VM_search_getfilename, // 77
3951 VM_itof, // isString
3955 VM_altstr_set, // 85
3969 VM_WriteEntity, // 408
3985 VM_drawresetcliparea,
3986 VM_getimagesize,// 460
3991 VM_cin_restart, // 465
4000 VM_M_setmousetarget,
4001 VM_M_getmousetarget,
4006 VM_M_keynumtostring,
4007 VM_M_findkeysforcommand,// 610
4008 VM_M_gethostcachestat,
4009 VM_M_gethostcachestring,
4010 VM_M_parseentitydata,
4011 VM_M_stringtokeynum,
4012 VM_M_resethostcachemasks,
4013 VM_M_sethostcachemaskstring,
4014 VM_M_sethostcachemasknumber,
4015 VM_M_resorthostcache,
4016 VM_M_sethostcachesort,
4017 VM_M_refreshhostcache,
4018 VM_M_gethostcachenumber,
4019 VM_M_gethostcacheindexforkey,
4020 VM_M_addwantedhostcachekey // 623
4023 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4025 void VM_M_Cmd_Init(void)
4030 void VM_M_Cmd_Reset(void)