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)
107 string altstr_ins(string altstr, float num, string set)
109 perhaps only : Menu : WriteMsg
110 ===============================
112 WriteByte(float data, float dest, float desto)
113 WriteChar(float data, float dest, float desto)
114 WriteShort(float data, float dest, float desto)
115 WriteLong(float data, float dest, float desto)
116 WriteAngle(float data, float dest, float desto)
117 WriteCoord(float data, float dest, float desto)
118 WriteString(string data, float dest, float desto)
119 WriteEntity(entity data, float dest, float desto)
121 Client & Menu : draw functions & video functions
122 ===================================================
124 float iscachedpic(string pic)
125 string precache_pic(string pic)
127 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
128 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
129 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
130 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
131 drawsetcliparea(float x, float y, float width, float height)
133 vector getimagesize(string pic)
135 float cin_open(string file, string name)
136 void cin_close(string name)
137 void cin_setstate(string name, float type)
138 float cin_getstate(string name)
139 void cin_restart(string name)
141 ==============================================================================
145 setkeydest(float dest)
147 setmousetarget(float target)
148 float getmousetarget()
150 callfunction(...,string function_name)
151 writetofile(float fhandle, entity ent)
152 float isfunction(string function_name)
153 vector getresolution(float number)
154 string keynumtostring(float keynum)
155 string findkeysforcommand(string command)
156 float getserverliststat(float type)
157 string getserverliststring(float fld, float hostnr)
159 parseentitydata(entity ent, string data)
161 float stringtokeynum(string key)
163 resetserverlistmasks()
164 setserverlistmaskstring(float mask, float fld, string str)
165 setserverlistmasknumber(float mask, float fld, float num, float op)
167 setserverlistsort(float field, float descending)
169 float getserverlistnumber(float fld, float hostnr)
170 float getserverlistindexforkey(string key)
171 addwantedserverlistkey(string key)
174 #include "quakedef.h"
175 #include "progdefs.h"
177 #include "clprogdefs.h"
178 #include "mprogdefs.h"
180 #include "cl_video.h"
182 //============================================================================
183 // nice helper macros
185 #ifndef VM_NOPARMCHECK
186 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
188 #define VM_SAFEPARMCOUNT(p,f)
191 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
193 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
195 #define e10 0,0,0,0,0,0,0,0,0,0
196 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
197 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
199 //============================================================================
202 // string zone mempool
203 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
205 // temp string handling
206 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
207 #define VM_STRINGTEMP_BUFFERS 16
208 #define VM_STRINGTEMP_LENGTH 4096
209 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
210 static int vm_string_tempindex = 0;
213 #define MAX_VMFILES 256
214 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
215 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
217 qfile_t *vm_files[MAX_PRVMFILES];
219 // qc fs search handling
220 #define MAX_VMSEARCHES 128
221 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
222 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
224 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
226 static char *VM_GetTempString(void)
229 s = vm_string_temp[vm_string_tempindex];
230 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
234 void VM_CheckEmptyString (char *s)
237 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
240 //============================================================================
243 void VM_VarString(int first, char *out, int outlength)
249 outend = out + outlength - 1;
250 for (i = first;i < prog->argc && out < outend;i++)
252 s = PRVM_G_STRING((OFS_PARM0+i*3));
253 while (out < outend && *s)
263 returns true if the extension is supported by the server
265 checkextension(extensionname)
269 // kind of helper function
270 static qboolean checkextension(char *name)
276 for (e = prog->extensionstring;*e;e++)
283 while (*e && *e != ' ')
285 if (e - start == len)
286 if (!strncasecmp(start, name, len))
294 void VM_checkextension (void)
296 VM_SAFEPARMCOUNT(1,VM_checkextension);
298 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
305 This is a TERMINAL error, which will kill off the entire prog.
314 char string[VM_STRINGTEMP_LENGTH];
316 VM_VarString(0, string, sizeof(string));
317 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
320 ed = PRVM_G_EDICT(prog->self->ofs);
324 PRVM_ERROR ("%s: Program error", PRVM_NAME);
331 Dumps out self, then an error message. The program is aborted and self is
332 removed, but the level can continue.
337 void VM_objerror (void)
340 char string[VM_STRINGTEMP_LENGTH];
342 VM_VarString(0, string, sizeof(string));
343 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
346 ed = PRVM_G_EDICT (prog->self->ofs);
352 // objerror has to display the object fields -> else call
353 PRVM_ERROR ("VM_objecterror: self not defined !\n");
358 VM_print (actually used only by client and menu)
367 char string[VM_STRINGTEMP_LENGTH];
369 VM_VarString(0, string, sizeof(string));
377 broadcast print to everyone on server
382 void VM_bprint (void)
384 char string[VM_STRINGTEMP_LENGTH];
388 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
392 VM_VarString(0, string, sizeof(string));
393 SV_BroadcastPrint(string);
398 VM_sprint (menu & client but only if server.active == true)
400 single print to a specific client
402 sprint(float clientnum,...[string])
405 void VM_sprint (void)
409 char string[VM_STRINGTEMP_LENGTH];
411 //find client for this entity
412 clientnum = PRVM_G_FLOAT(OFS_PARM0);
413 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
415 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
419 client = svs.clients + clientnum;
420 VM_VarString(1, string, sizeof(string));
421 MSG_WriteChar(&client->message,svc_print);
422 MSG_WriteString(&client->message, string);
429 single print to the screen
431 centerprint(clientent, value)
434 void VM_centerprint (void)
436 char string[VM_STRINGTEMP_LENGTH];
438 VM_VarString(0, string, sizeof(string));
439 SCR_CenterPrint(string);
446 vector normalize(vector)
449 void VM_normalize (void)
455 VM_SAFEPARMCOUNT(1,VM_normalize);
457 value1 = PRVM_G_VECTOR(OFS_PARM0);
459 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
463 newvalue[0] = newvalue[1] = newvalue[2] = 0;
467 newvalue[0] = value1[0] * new;
468 newvalue[1] = value1[1] * new;
469 newvalue[2] = value1[2] * new;
472 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
487 VM_SAFEPARMCOUNT(1,VM_vlen);
489 value1 = PRVM_G_VECTOR(OFS_PARM0);
491 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
494 PRVM_G_FLOAT(OFS_RETURN) = new;
501 float vectoyaw(vector)
504 void VM_vectoyaw (void)
509 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
511 value1 = PRVM_G_VECTOR(OFS_PARM0);
513 if (value1[1] == 0 && value1[0] == 0)
517 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
522 PRVM_G_FLOAT(OFS_RETURN) = yaw;
530 vector vectoangles(vector)
533 void VM_vectoangles (void)
539 VM_SAFEPARMCOUNT(1,VM_vectoangles);
541 value1 = PRVM_G_VECTOR(OFS_PARM0);
543 if (value1[1] == 0 && value1[0] == 0)
553 // LordHavoc: optimized a bit
556 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
560 else if (value1[1] > 0)
565 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
566 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
571 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
572 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
573 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
580 Returns a number from 0<= num < 1
585 void VM_random (void)
587 VM_SAFEPARMCOUNT(0,VM_random);
589 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
596 Each entity can have eight independant sound sources, like voice,
599 Channel 0 is an auto-allocate channel, the others override anything
600 already running on that entity/channel pair.
602 An attenuation of 0 will play full volume everywhere in the level.
603 Larger attenuations will drop off.
616 entity = G_EDICT(OFS_PARM0);
617 channel = G_FLOAT(OFS_PARM1);
618 sample = G_STRING(OFS_PARM2);
619 volume = G_FLOAT(OFS_PARM3) * 255;
620 attenuation = G_FLOAT(OFS_PARM4);
622 if (volume < 0 || volume > 255)
623 Host_Error ("SV_StartSound: volume = %i", volume);
625 if (attenuation < 0 || attenuation > 4)
626 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
628 if (channel < 0 || channel > 7)
629 Host_Error ("SV_StartSound: channel = %i", channel);
631 SV_StartSound (entity, channel, sample, volume, attenuation);
639 localsound(string sample)
642 void VM_localsound(void)
646 VM_SAFEPARMCOUNT(1,VM_localsound);
648 s = PRVM_G_STRING(OFS_PARM0);
650 if(!S_LocalSound (s))
652 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
653 PRVM_G_FLOAT(OFS_RETURN) = -4;
657 PRVM_G_FLOAT(OFS_RETURN) = 1;
669 PRVM_ERROR ("%s: break statement", PRVM_NAME);
672 //============================================================================
678 Sends text over to the client's execution buffer
680 [localcmd (string) or]
684 void VM_localcmd (void)
686 VM_SAFEPARMCOUNT(1,VM_localcmd);
688 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
700 VM_SAFEPARMCOUNT(1,VM_cvar);
702 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
709 const string str_cvar (string)
712 void VM_str_cvar(void)
715 const char *cvar_string;
716 VM_SAFEPARMCOUNT(1,VM_str_cvar);
718 name = PRVM_G_STRING(OFS_PARM0);
721 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
723 VM_CheckEmptyString(name);
725 out = VM_GetTempString();
727 cvar_string = Cvar_VariableString(name);
729 strcpy(out, cvar_string);
731 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
738 void cvar_set (string,string)
741 void VM_cvar_set (void)
743 VM_SAFEPARMCOUNT(2,VM_cvar_set);
745 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
755 void VM_dprint (void)
757 char string[VM_STRINGTEMP_LENGTH];
758 if (developer.integer)
760 VM_VarString(0, string, sizeof(string));
761 Con_Printf("%s: %s", PRVM_NAME, string);
778 VM_SAFEPARMCOUNT(1, VM_ftos);
780 v = PRVM_G_FLOAT(OFS_PARM0);
782 s = VM_GetTempString();
783 if ((float)((int)v) == v)
784 sprintf(s, "%i", (int)v);
787 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
802 VM_SAFEPARMCOUNT(1,VM_fabs);
804 v = PRVM_G_FLOAT(OFS_PARM0);
805 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
820 VM_SAFEPARMCOUNT(1,VM_vtos);
822 s = VM_GetTempString();
823 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]);
824 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
839 VM_SAFEPARMCOUNT(1, VM_etos);
841 s = VM_GetTempString();
842 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
843 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
850 float stof(...[string])
855 char string[VM_STRINGTEMP_LENGTH];
856 VM_VarString(0, string, sizeof(string));
857 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
861 ========================
865 ========================
869 VM_SAFEPARMCOUNT(1, VM_itof);
870 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
874 ========================
878 ========================
883 VM_SAFEPARMCOUNT(1, VM_ftoi);
885 ent = PRVM_G_FLOAT(OFS_PARM0);
886 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
887 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
889 PRVM_G_INT(OFS_RETURN) = ent;
903 prog->xfunction->builtinsprofile += 20;
904 ed = PRVM_ED_Alloc();
916 void VM_remove (void)
919 prog->xfunction->builtinsprofile += 20;
921 VM_SAFEPARMCOUNT(1, VM_remove);
923 ed = PRVM_G_EDICT(OFS_PARM0);
924 // if (ed == prog->edicts)
925 // PRVM_ERROR ("remove: tried to remove world\n");
926 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
927 // Host_Error("remove: tried to remove a client\n");
935 entity find(entity start, .string field, string match)
946 VM_SAFEPARMCOUNT(3,VM_find);
948 e = PRVM_G_EDICTNUM(OFS_PARM0);
949 f = PRVM_G_INT(OFS_PARM1);
950 s = PRVM_G_STRING(OFS_PARM2);
954 // return reserved edict 0 (could be used for whatever the prog wants)
955 VM_RETURN_EDICT(prog->edicts);
959 for (e++ ; e < prog->num_edicts ; e++)
961 prog->xfunction->builtinsprofile++;
962 ed = PRVM_EDICT_NUM(e);
965 t = PRVM_E_STRING(ed,f);
975 VM_RETURN_EDICT(prog->edicts);
982 entity findfloat(entity start, .float field, float match)
983 entity findentity(entity start, .entity field, entity match)
986 // LordHavoc: added this for searching float, int, and entity reference fields
987 void VM_findfloat (void)
994 VM_SAFEPARMCOUNT(3,VM_findfloat);
996 e = PRVM_G_EDICTNUM(OFS_PARM0);
997 f = PRVM_G_INT(OFS_PARM1);
998 s = PRVM_G_FLOAT(OFS_PARM2);
1000 for (e++ ; e < prog->num_edicts ; e++)
1002 prog->xfunction->builtinsprofile++;
1003 ed = PRVM_EDICT_NUM(e);
1006 if (PRVM_E_FLOAT(ed,f) == s)
1008 VM_RETURN_EDICT(ed);
1013 VM_RETURN_EDICT(prog->edicts);
1020 entity findchain(.string field, string match)
1023 int PRVM_ED_FindFieldOffset(const char *field);
1024 // chained search for strings in entity fields
1025 // entity(.string field, string match) findchain = #402;
1026 void VM_findchain (void)
1032 prvm_edict_t *ent, *chain;
1034 VM_SAFEPARMCOUNT(2,VM_findchain);
1036 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1037 if(!prog->flag & PRVM_FE_CHAIN)
1038 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1040 chain_of = PRVM_ED_FindFieldOffset ("chain");
1042 chain = prog->edicts;
1044 f = PRVM_G_INT(OFS_PARM0);
1045 s = PRVM_G_STRING(OFS_PARM1);
1048 VM_RETURN_EDICT(prog->edicts);
1052 ent = PRVM_NEXT_EDICT(prog->edicts);
1053 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1055 prog->xfunction->builtinsprofile++;
1058 t = PRVM_E_STRING(ent,f);
1064 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1068 VM_RETURN_EDICT(chain);
1075 entity findchainfloat(.string field, float match)
1076 entity findchainentity(.string field, entity match)
1079 // LordHavoc: chained search for float, int, and entity reference fields
1080 // entity(.string field, float match) findchainfloat = #403;
1081 void VM_findchainfloat (void)
1087 prvm_edict_t *ent, *chain;
1089 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1091 if(!prog->flag & PRVM_FE_CHAIN)
1092 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1094 chain_of = PRVM_ED_FindFieldOffset ("chain");
1096 chain = (prvm_edict_t *)prog->edicts;
1098 f = PRVM_G_INT(OFS_PARM0);
1099 s = PRVM_G_FLOAT(OFS_PARM1);
1101 ent = PRVM_NEXT_EDICT(prog->edicts);
1102 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1104 prog->xfunction->builtinsprofile++;
1107 if (PRVM_E_FLOAT(ent,f) != s)
1110 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1114 VM_RETURN_EDICT(chain);
1121 string precache_file(string)
1124 void VM_precache_file (void)
1125 { // precache_file is only used to copy files with qcc, it does nothing
1126 VM_SAFEPARMCOUNT(1,VM_precache_file);
1128 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1135 used instead of the other VM_precache_* functions in the builtin list
1139 void VM_precache_error (void)
1141 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1148 string precache_sound (string sample)
1151 void VM_precache_sound (void)
1155 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1157 s = PRVM_G_STRING(OFS_PARM0);
1158 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1159 VM_CheckEmptyString (s);
1161 if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
1162 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1172 void VM_coredump (void)
1174 VM_SAFEPARMCOUNT(0,VM_coredump);
1176 Cbuf_AddText("prvm_edicts ");
1177 Cbuf_AddText(PRVM_NAME);
1188 void PRVM_StackTrace(void);
1189 void VM_stackdump (void)
1191 VM_SAFEPARMCOUNT(0, VM_stackdump);
1206 VM_SAFEPARMCOUNT(0, VM_crash);
1208 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1218 void VM_traceon (void)
1220 VM_SAFEPARMCOUNT(0,VM_traceon);
1232 void VM_traceoff (void)
1234 VM_SAFEPARMCOUNT(0,VM_traceoff);
1236 prog->trace = false;
1246 void VM_eprint (void)
1248 VM_SAFEPARMCOUNT(1,VM_eprint);
1250 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1264 VM_SAFEPARMCOUNT(1,VM_rint);
1266 f = PRVM_G_FLOAT(OFS_PARM0);
1268 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1270 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1280 void VM_floor (void)
1282 VM_SAFEPARMCOUNT(1,VM_floor);
1284 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1296 VM_SAFEPARMCOUNT(1,VM_ceil);
1298 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1306 entity nextent(entity)
1309 void VM_nextent (void)
1314 i = PRVM_G_EDICTNUM(OFS_PARM0);
1317 prog->xfunction->builtinsprofile++;
1319 if (i == prog->num_edicts)
1321 VM_RETURN_EDICT(prog->edicts);
1324 ent = PRVM_EDICT_NUM(i);
1325 if (!ent->p.e->free)
1327 VM_RETURN_EDICT(ent);
1334 ===============================================================================
1337 used only for client and menu
1338 severs uses VM_SV_...
1340 Write*(* data, float type, float to)
1342 ===============================================================================
1345 #define MSG_BROADCAST 0 // unreliable to all
1346 #define MSG_ONE 1 // reliable to one (msg_entity)
1347 #define MSG_ALL 2 // reliable to all
1348 #define MSG_INIT 3 // write to the init string
1350 sizebuf_t *VM_WriteDest (void)
1356 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1358 dest = G_FLOAT(OFS_PARM1);
1362 return &sv.datagram;
1365 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1366 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1367 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1369 return &svs.clients[destclient].message;
1372 return &sv.reliable_datagram;
1378 PRVM_ERROR ("WriteDest: bad destination");
1385 void VM_WriteByte (void)
1387 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1390 void VM_WriteChar (void)
1392 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1395 void VM_WriteShort (void)
1397 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1400 void VM_WriteLong (void)
1402 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1405 void VM_WriteAngle (void)
1407 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1410 void VM_WriteCoord (void)
1412 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1415 void VM_WriteString (void)
1417 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1420 void VM_WriteEntity (void)
1422 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1425 //=============================================================================
1432 changelevel(string map)
1435 void VM_changelevel (void)
1439 VM_SAFEPARMCOUNT(1, VM_changelevel);
1443 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1447 // make sure we don't issue two changelevels
1448 if (svs.changelevel_issued)
1450 svs.changelevel_issued = true;
1452 s = G_STRING(OFS_PARM0);
1453 Cbuf_AddText (va("changelevel %s\n",s));
1465 VM_SAFEPARMCOUNT(1,VM_sin);
1466 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1477 VM_SAFEPARMCOUNT(1,VM_cos);
1478 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1490 VM_SAFEPARMCOUNT(1,VM_sqrt);
1491 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1498 Returns a vector of length < 1 and > 0
1503 void VM_randomvec (void)
1508 VM_SAFEPARMCOUNT(0, VM_randomvec);
1513 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1514 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1515 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1517 while (DotProduct(temp, temp) >= 1);
1518 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1521 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1522 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1523 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1524 // length returned always > 0
1525 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1526 VectorScale(temp,length, temp);*/
1527 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1530 //=============================================================================
1536 float registercvar (string name, string value, float flags)
1539 void VM_registercvar (void)
1544 VM_SAFEPARMCOUNT(3,VM_registercvar);
1546 name = PRVM_G_STRING(OFS_PARM0);
1547 value = PRVM_G_STRING(OFS_PARM1);
1548 flags = PRVM_G_FLOAT(OFS_PARM2);
1549 PRVM_G_FLOAT(OFS_RETURN) = 0;
1551 if(flags > CVAR_MAXFLAGSVAL)
1554 // first check to see if it has already been defined
1555 if (Cvar_FindVar (name))
1558 // check for overlap with a command
1559 if (Cmd_Exists (name))
1561 Con_Printf("VM_registercvar: %s is a command\n", name);
1565 Cvar_Get(name, value, flags);
1567 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1574 returns the minimum of two supplied floats
1576 float min(float a, float b, ...[float])
1581 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1582 if (prog->argc == 2)
1583 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1584 else if (prog->argc >= 3)
1587 float f = PRVM_G_FLOAT(OFS_PARM0);
1588 for (i = 1;i < prog->argc;i++)
1589 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1590 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1591 PRVM_G_FLOAT(OFS_RETURN) = f;
1594 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1601 returns the maximum of two supplied floats
1603 float max(float a, float b, ...[float])
1608 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1609 if (prog->argc == 2)
1610 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1611 else if (prog->argc >= 3)
1614 float f = PRVM_G_FLOAT(OFS_PARM0);
1615 for (i = 1;i < prog->argc;i++)
1616 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1617 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1618 PRVM_G_FLOAT(OFS_RETURN) = f;
1621 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1628 returns number bounded by supplied range
1630 float bound(float min, float value, float max)
1633 void VM_bound (void)
1635 VM_SAFEPARMCOUNT(3,VM_bound);
1636 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1643 returns a raised to power b
1645 float pow(float a, float b)
1650 VM_SAFEPARMCOUNT(2,VM_pow);
1651 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1658 copies data from one entity to another
1660 copyentity(entity src, entity dst)
1663 void VM_copyentity (void)
1665 prvm_edict_t *in, *out;
1666 VM_SAFEPARMCOUNT(2,VM_copyentity);
1667 in = PRVM_G_EDICT(OFS_PARM0);
1668 out = PRVM_G_EDICT(OFS_PARM1);
1669 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1676 sets the color of a client and broadcasts the update to all connected clients
1678 setcolor(clientent, value)
1681 /*void PF_setcolor (void)
1687 entnum = G_EDICTNUM(OFS_PARM0);
1688 i = G_FLOAT(OFS_PARM1);
1690 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1692 Con_Print("tried to setcolor a non-client\n");
1696 client = svs.clients + entnum-1;
1697 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1700 client->old_colors = i;
1701 client->edict->v->team = (i & 15) + 1;
1703 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1704 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1705 MSG_WriteByte (&sv.reliable_datagram, i);
1708 void VM_Files_Init(void)
1710 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1713 void VM_Files_CloseAll(void)
1716 for (i = 0;i < MAX_VMFILES;i++)
1719 FS_Close(VM_FILES[i]);
1720 //VM_FILES[i] = NULL;
1722 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1729 float fopen(string filename, float mode)
1732 // float(string filename, float mode) fopen = #110;
1733 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1734 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1738 char *modestring, *filename;
1740 VM_SAFEPARMCOUNT(2,VM_fopen);
1742 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1743 if (VM_FILES[filenum] == NULL)
1745 if (filenum >= MAX_VMFILES)
1747 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1748 PRVM_G_FLOAT(OFS_RETURN) = -2;
1751 mode = PRVM_G_FLOAT(OFS_PARM1);
1754 case 0: // FILE_READ
1757 case 1: // FILE_APPEND
1760 case 2: // FILE_WRITE
1764 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1765 PRVM_G_FLOAT(OFS_RETURN) = -3;
1768 filename = PRVM_G_STRING(OFS_PARM0);
1769 // .. is parent directory on many platforms
1770 // / is parent directory on Amiga
1771 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1772 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1773 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1775 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1776 PRVM_G_FLOAT(OFS_RETURN) = -4;
1779 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
1780 if (VM_FILES[filenum] == NULL && mode == 0)
1781 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false, false);
1783 if (VM_FILES[filenum] == NULL)
1784 PRVM_G_FLOAT(OFS_RETURN) = -1;
1786 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1793 fclose(float fhandle)
1796 //void(float fhandle) fclose = #111; // closes a file
1797 void VM_fclose(void)
1801 VM_SAFEPARMCOUNT(1,VM_fclose);
1803 filenum = PRVM_G_FLOAT(OFS_PARM0);
1804 if (filenum < 0 || filenum >= MAX_VMFILES)
1806 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1809 if (VM_FILES[filenum] == NULL)
1811 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1814 FS_Close(VM_FILES[filenum]);
1815 VM_FILES[filenum] = NULL;
1822 string fgets(float fhandle)
1825 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1829 static char string[VM_STRINGTEMP_LENGTH];
1832 VM_SAFEPARMCOUNT(1,VM_fgets);
1834 filenum = PRVM_G_FLOAT(OFS_PARM0);
1835 if (filenum < 0 || filenum >= MAX_VMFILES)
1837 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1840 if (VM_FILES[filenum] == NULL)
1842 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1848 c = FS_Getc(VM_FILES[filenum]);
1849 if (c == '\r' || c == '\n' || c < 0)
1851 if (end < VM_STRINGTEMP_LENGTH - 1)
1855 // remove \n following \r
1858 c = FS_Getc(VM_FILES[filenum]);
1860 FS_UnGetc(VM_FILES[filenum], (unsigned char)c);
1862 if (developer.integer >= 3)
1863 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1865 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1867 PRVM_G_INT(OFS_RETURN) = 0;
1874 fputs(float fhandle, string s)
1877 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1881 char string[VM_STRINGTEMP_LENGTH];
1884 VM_SAFEPARMCOUNT(2,VM_fputs);
1886 filenum = PRVM_G_FLOAT(OFS_PARM0);
1887 if (filenum < 0 || filenum >= MAX_VMFILES)
1889 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1892 if (VM_FILES[filenum] == NULL)
1894 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1897 VM_VarString(1, string, sizeof(string));
1898 if ((stringlength = strlen(string)))
1899 FS_Write(VM_FILES[filenum], string, stringlength);
1900 if (developer.integer)
1901 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1908 float strlen(string s)
1911 //float(string s) strlen = #114; // returns how many characters are in a string
1912 void VM_strlen(void)
1916 VM_SAFEPARMCOUNT(1,VM_strlen);
1918 s = PRVM_G_STRING(OFS_PARM0);
1920 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1922 PRVM_G_FLOAT(OFS_RETURN) = 0;
1929 string strcat(string,string,...[string])
1932 //string(string s1, string s2) strcat = #115;
1933 // concatenates two strings (for example "abc", "def" would return "abcdef")
1934 // and returns as a tempstring
1935 void VM_strcat(void)
1940 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1942 s = VM_GetTempString();
1943 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1944 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1951 string substring(string s, float start, float length)
1954 // string(string s, float start, float length) substring = #116;
1955 // returns a section of a string as a tempstring
1956 void VM_substring(void)
1958 int i, start, length;
1961 VM_SAFEPARMCOUNT(3,VM_substring);
1963 string = VM_GetTempString();
1964 s = PRVM_G_STRING(OFS_PARM0);
1965 start = PRVM_G_FLOAT(OFS_PARM1);
1966 length = PRVM_G_FLOAT(OFS_PARM2);
1969 for (i = 0;i < start && *s;i++, s++);
1970 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1973 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1980 vector stov(string s)
1983 //vector(string s) stov = #117; // returns vector value from a string
1986 char string[VM_STRINGTEMP_LENGTH];
1988 VM_SAFEPARMCOUNT(1,VM_stov);
1990 VM_VarString(0, string, sizeof(string));
1991 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1998 string strzone(string s)
2001 //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)
2002 void VM_strzone(void)
2006 VM_SAFEPARMCOUNT(1,VM_strzone);
2008 in = PRVM_G_STRING(OFS_PARM0);
2009 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
2011 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2021 //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!!!)
2022 void VM_strunzone(void)
2025 VM_SAFEPARMCOUNT(1,VM_strunzone);
2027 str = PRVM_G_STRING(OFS_PARM0);
2028 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2029 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2036 VM_command (used by client and menu)
2038 clientcommand(float client, string s) (for client and menu)
2041 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2042 //this function originally written by KrimZon, made shorter by LordHavoc
2043 void VM_clcommand (void)
2045 client_t *temp_client;
2048 VM_SAFEPARMCOUNT(2,VM_clcommand);
2050 i = PRVM_G_FLOAT(OFS_PARM0);
2051 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2053 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2057 temp_client = host_client;
2058 host_client = svs.clients + i;
2059 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2060 host_client = temp_client;
2068 float tokenize(string s)
2071 //float(string s) tokenize = #441;
2072 // takes apart a string into individal words (access them with argv), returns how many
2073 // this function originally written by KrimZon, made shorter by LordHavoc
2074 static char **tokens = NULL;
2075 static int max_tokens, num_tokens = 0;
2076 void VM_tokenize (void)
2081 VM_SAFEPARMCOUNT(1,VM_tokenize);
2083 str = PRVM_G_STRING(OFS_PARM0);
2088 for (i=0;i<num_tokens;i++)
2094 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2095 max_tokens = strlen(str);
2097 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2099 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2100 strcpy(tokens[num_tokens], com_token);
2103 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2110 string argv(float n)
2113 //string(float n) argv = #442;
2114 // returns a word from the tokenized string (returns nothing for an invalid index)
2115 // this function originally written by KrimZon, made shorter by LordHavoc
2120 VM_SAFEPARMCOUNT(1,VM_argv);
2122 token_num = PRVM_G_FLOAT(OFS_PARM0);
2123 if (token_num >= 0 && token_num < num_tokens)
2124 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2126 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2130 //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)
2131 void PF_setattachment (void)
2133 edict_t *e = G_EDICT(OFS_PARM0);
2134 edict_t *tagentity = G_EDICT(OFS_PARM1);
2135 char *tagname = G_STRING(OFS_PARM2);
2140 if (tagentity == NULL)
2141 tagentity = sv.edicts;
2143 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2145 v->edict = EDICT_TO_PROG(tagentity);
2147 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2150 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2152 modelindex = (int)tagentity->v->modelindex;
2153 if (modelindex >= 0 && modelindex < MAX_MODELS)
2155 model = sv.models[modelindex];
2156 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2157 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2158 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2160 // FIXME: use a model function to get tag info (need to handle skeletal)
2161 if (v->_float == 0 && model->alias.aliasnum_tags)
2162 for (i = 0;i < model->alias.aliasnum_tags;i++)
2163 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2166 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);
2169 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));
2180 void VM_isserver(void)
2182 VM_SAFEPARMCOUNT(0,VM_serverstate);
2184 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2194 void VM_clientcount(void)
2196 VM_SAFEPARMCOUNT(0,VM_clientcount);
2198 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2208 void VM_clientstate(void)
2210 VM_SAFEPARMCOUNT(0,VM_clientstate);
2212 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2219 float getostype(void)
2221 */ // not used at the moment -> not included in the common list
2222 void VM_getostype(void)
2224 VM_SAFEPARMCOUNT(0,VM_getostype);
2229 OS_MAC - not supported
2233 PRVM_G_FLOAT(OFS_RETURN) = 0;
2235 PRVM_G_FLOAT(OFS_RETURN) = 2;
2237 PRVM_G_FLOAT(OFS_RETURN) = 1;
2245 vector getmousepos()
2248 void VM_getmousepos(void)
2251 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2253 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2254 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2255 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2265 void VM_gettime(void)
2267 VM_SAFEPARMCOUNT(0,VM_gettime);
2269 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2276 loadfromdata(string data)
2279 void VM_loadfromdata(void)
2281 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2283 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2287 ========================
2288 VM_M_parseentitydata
2290 parseentitydata(entity ent, string data)
2291 ========================
2293 void VM_M_parseentitydata(void)
2298 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2300 // get edict and test it
2301 ent = PRVM_G_EDICT(OFS_PARM0);
2303 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2305 data = PRVM_G_STRING(OFS_PARM1);
2307 // parse the opening brace
2308 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2309 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2311 PRVM_ED_ParseEdict (data, ent);
2318 loadfromfile(string file)
2321 void VM_loadfromfile(void)
2326 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2328 filename = PRVM_G_STRING(OFS_PARM0);
2329 // .. is parent directory on many platforms
2330 // / is parent directory on Amiga
2331 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2332 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2333 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2335 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2336 PRVM_G_FLOAT(OFS_RETURN) = -4;
2340 // not conform with VM_fopen
2341 data = FS_LoadFile(filename, tempmempool, false);
2343 PRVM_G_FLOAT(OFS_RETURN) = -1;
2345 PRVM_ED_LoadFromFile(data);
2356 float mod(float val, float m)
2359 void VM_modulo(void)
2362 VM_SAFEPARMCOUNT(2,VM_module);
2364 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2365 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2367 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2370 void VM_Search_Init(void)
2372 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2375 void VM_Search_Reset(void)
2378 // reset the fssearch list
2379 for(i = 0; i < MAX_VMSEARCHES; i++)
2380 if(VM_SEARCHLIST[i])
2381 FS_FreeSearch(VM_SEARCHLIST[i]);
2382 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2389 float search_begin(string pattern, float caseinsensitive, float quiet)
2392 void VM_search_begin(void)
2396 int caseinsens, quiet;
2398 VM_SAFEPARMCOUNT(3, VM_search_begin);
2400 pattern = PRVM_G_STRING(OFS_PARM0);
2402 VM_CheckEmptyString(pattern);
2404 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2405 quiet = PRVM_G_FLOAT(OFS_PARM2);
2407 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2408 if(!VM_SEARCHLIST[handle])
2411 if(handle >= MAX_VMSEARCHES)
2413 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2414 PRVM_G_FLOAT(OFS_RETURN) = -2;
2418 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2419 PRVM_G_FLOAT(OFS_RETURN) = -1;
2421 PRVM_G_FLOAT(OFS_RETURN) = handle;
2428 void search_end(float handle)
2431 void VM_search_end(void)
2434 VM_SAFEPARMCOUNT(1, VM_search_end);
2436 handle = PRVM_G_FLOAT(OFS_PARM0);
2438 if(handle < 0 || handle >= MAX_VMSEARCHES)
2440 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2443 if(VM_SEARCHLIST[handle] == NULL)
2445 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2449 FS_FreeSearch(VM_SEARCHLIST[handle]);
2450 VM_SEARCHLIST[handle] = NULL;
2457 float search_getsize(float handle)
2460 void VM_search_getsize(void)
2463 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2465 handle = PRVM_G_FLOAT(OFS_PARM0);
2467 if(handle < 0 || handle >= MAX_VMSEARCHES)
2469 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2472 if(VM_SEARCHLIST[handle] == NULL)
2474 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2478 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2483 VM_search_getfilename
2485 string search_getfilename(float handle, float num)
2488 void VM_search_getfilename(void)
2490 int handle, filenum;
2492 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2494 handle = PRVM_G_FLOAT(OFS_PARM0);
2495 filenum = PRVM_G_FLOAT(OFS_PARM1);
2497 if(handle < 0 || handle >= MAX_VMSEARCHES)
2499 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2502 if(VM_SEARCHLIST[handle] == NULL)
2504 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2507 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2509 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2513 tmp = VM_GetTempString();
2514 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2516 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2523 string chr(float ascii)
2529 VM_SAFEPARMCOUNT(1, VM_chr);
2531 tmp = VM_GetTempString();
2532 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2535 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2538 //=============================================================================
2539 // Draw builtins (client & menu)
2545 float iscachedpic(string pic)
2548 void VM_iscachedpic(void)
2550 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2552 // drawq hasnt such a function, thus always return true
2553 PRVM_G_FLOAT(OFS_RETURN) = false;
2560 string precache_pic(string pic)
2563 void VM_precache_pic(void)
2567 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2569 s = PRVM_G_STRING(OFS_PARM0);
2570 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2573 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2575 VM_CheckEmptyString (s);
2577 if(!Draw_CachePic(s))
2578 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2588 void VM_freepic(void)
2592 VM_SAFEPARMCOUNT(1,VM_freepic);
2594 s = PRVM_G_STRING(OFS_PARM0);
2597 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2599 VM_CheckEmptyString (s);
2608 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2611 void VM_drawcharacter(void)
2613 float *pos,*scale,*rgb;
2616 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2618 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2621 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2622 PRVM_G_FLOAT(OFS_RETURN) = -1;
2626 pos = PRVM_G_VECTOR(OFS_PARM0);
2627 scale = PRVM_G_VECTOR(OFS_PARM2);
2628 rgb = PRVM_G_VECTOR(OFS_PARM3);
2629 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2631 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2633 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2634 PRVM_G_FLOAT(OFS_RETURN) = -2;
2638 if(pos[2] || scale[2])
2639 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")));
2641 if(!scale[0] || !scale[1])
2643 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2644 PRVM_G_FLOAT(OFS_RETURN) = -3;
2648 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2649 PRVM_G_FLOAT(OFS_RETURN) = 1;
2656 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2659 void VM_drawstring(void)
2661 float *pos,*scale,*rgb;
2664 VM_SAFEPARMCOUNT(6,VM_drawstring);
2666 string = PRVM_G_STRING(OFS_PARM1);
2669 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2670 PRVM_G_FLOAT(OFS_RETURN) = -1;
2674 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2676 pos = PRVM_G_VECTOR(OFS_PARM0);
2677 scale = PRVM_G_VECTOR(OFS_PARM2);
2678 rgb = PRVM_G_VECTOR(OFS_PARM3);
2679 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2681 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2683 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2684 PRVM_G_FLOAT(OFS_RETURN) = -2;
2688 if(!scale[0] || !scale[1])
2690 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2691 PRVM_G_FLOAT(OFS_RETURN) = -3;
2695 if(pos[2] || scale[2])
2696 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")));
2698 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2699 PRVM_G_FLOAT(OFS_RETURN) = 1;
2705 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2708 void VM_drawpic(void)
2711 float *size, *pos, *rgb;
2714 VM_SAFEPARMCOUNT(6,VM_drawpic);
2716 pic = PRVM_G_STRING(OFS_PARM1);
2720 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2721 PRVM_G_FLOAT(OFS_RETURN) = -1;
2725 VM_CheckEmptyString (pic);
2727 // is pic cached ? no function yet for that
2730 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2731 PRVM_G_FLOAT(OFS_RETURN) = -4;
2735 pos = PRVM_G_VECTOR(OFS_PARM0);
2736 size = PRVM_G_VECTOR(OFS_PARM2);
2737 rgb = PRVM_G_VECTOR(OFS_PARM3);
2738 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2740 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2742 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2743 PRVM_G_FLOAT(OFS_RETURN) = -2;
2747 if(pos[2] || size[2])
2748 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")));
2750 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2751 PRVM_G_FLOAT(OFS_RETURN) = 1;
2758 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2761 void VM_drawfill(void)
2763 float *size, *pos, *rgb;
2766 VM_SAFEPARMCOUNT(5,VM_drawfill);
2769 pos = PRVM_G_VECTOR(OFS_PARM0);
2770 size = PRVM_G_VECTOR(OFS_PARM1);
2771 rgb = PRVM_G_VECTOR(OFS_PARM2);
2772 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2774 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2776 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2777 PRVM_G_FLOAT(OFS_RETURN) = -2;
2781 if(pos[2] || size[2])
2782 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")));
2784 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2785 PRVM_G_FLOAT(OFS_RETURN) = 1;
2792 drawsetcliparea(float x, float y, float width, float height)
2795 void VM_drawsetcliparea(void)
2798 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2800 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2801 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2802 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2803 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2805 DrawQ_SetClipArea(x, y, w, h);
2810 VM_drawresetcliparea
2815 void VM_drawresetcliparea(void)
2817 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2819 DrawQ_ResetClipArea();
2826 vector getimagesize(string pic)
2829 void VM_getimagesize(void)
2834 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2836 p = PRVM_G_STRING(OFS_PARM0);
2839 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2841 VM_CheckEmptyString (p);
2843 pic = Draw_CachePic (p);
2845 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2846 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2847 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2850 // CL_Video interface functions
2853 ========================
2856 float cin_open(string file, string name)
2857 ========================
2859 void VM_cin_open( void )
2864 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2866 file = PRVM_G_STRING( OFS_PARM0 );
2867 name = PRVM_G_STRING( OFS_PARM1 );
2869 VM_CheckEmptyString( file );
2870 VM_CheckEmptyString( name );
2872 if( CL_OpenVideo( file, name, MENUOWNER ) )
2873 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2875 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2879 ========================
2882 void cin_close(string name)
2883 ========================
2885 void VM_cin_close( void )
2889 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2891 name = PRVM_G_STRING( OFS_PARM0 );
2892 VM_CheckEmptyString( name );
2894 CL_CloseVideo( CL_GetVideo( name ) );
2898 ========================
2900 void cin_setstate(string name, float type)
2901 ========================
2903 void VM_cin_setstate( void )
2906 clvideostate_t state;
2909 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2911 name = PRVM_G_STRING( OFS_PARM0 );
2912 VM_CheckEmptyString( name );
2914 state = PRVM_G_FLOAT( OFS_PARM1 );
2916 video = CL_GetVideo( name );
2917 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2918 CL_SetVideoState( video, state );
2922 ========================
2925 float cin_getstate(string name)
2926 ========================
2928 void VM_cin_getstate( void )
2933 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2935 name = PRVM_G_STRING( OFS_PARM0 );
2936 VM_CheckEmptyString( name );
2938 video = CL_GetVideo( name );
2940 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2942 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2946 ========================
2949 void cin_restart(string name)
2950 ========================
2952 void VM_cin_restart( void )
2957 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2959 name = PRVM_G_STRING( OFS_PARM0 );
2960 VM_CheckEmptyString( name );
2962 video = CL_GetVideo( name );
2964 CL_RestartVideo( video );
2967 ////////////////////////////////////////
2968 // AltString functions
2969 ////////////////////////////////////////
2972 ========================
2975 float altstr_count(string)
2976 ========================
2978 void VM_altstr_count( void )
2983 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2985 altstr = PRVM_G_STRING( OFS_PARM0 );
2986 //VM_CheckEmptyString( altstr );
2988 for( count = 0, pos = altstr ; *pos ; pos++ )
2989 if( *pos == '\\' && !*++pos )
2991 else if( *pos == '\'' )
2994 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2998 ========================
3001 string altstr_prepare(string)
3002 ========================
3004 void VM_altstr_prepare( void )
3010 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3012 instr = PRVM_G_STRING( OFS_PARM0 );
3013 //VM_CheckEmptyString( instr );
3014 outstr = VM_GetTempString();
3016 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3025 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3029 ========================
3032 string altstr_get(string, float)
3033 ========================
3035 void VM_altstr_get( void )
3037 char *altstr, *pos, *outstr, *out;
3040 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3042 altstr = PRVM_G_STRING( OFS_PARM0 );
3043 //VM_CheckEmptyString( altstr );
3045 count = PRVM_G_FLOAT( OFS_PARM1 );
3046 count = count * 2 + 1;
3048 for( pos = altstr ; *pos && count ; pos++ )
3049 if( *pos == '\\' && !*++pos )
3051 else if( *pos == '\'' )
3055 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3059 outstr = VM_GetTempString();
3060 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3061 if( *pos == '\\' ) {
3066 } else if( *pos == '\'' )
3072 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3076 ========================
3079 string altstr_set(string altstr, float num, string set)
3080 ========================
3082 void VM_altstr_set( void )
3089 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3091 altstr = PRVM_G_STRING( OFS_PARM0 );
3092 //VM_CheckEmptyString( altstr );
3094 num = PRVM_G_FLOAT( OFS_PARM1 );
3096 str = PRVM_G_STRING( OFS_PARM2 );
3097 //VM_CheckEmptyString( str );
3099 outstr = out = VM_GetTempString();
3100 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3101 if( *in == '\\' && !*++in )
3103 else if( *in == '\'' )
3107 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3111 for( ; *str; *out++ = *str++ );
3112 // now jump over the old contents
3114 if( *in == '\'' || (*in == '\\' && !*++in) )
3118 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3123 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3127 ========================
3130 string altstr_ins(string altstr, float num, string set)
3131 ========================
3133 void VM_altstr_ins(void)
3143 in = instr = PRVM_G_STRING( OFS_PARM0 );
3144 num = PRVM_G_FLOAT( OFS_PARM1 );
3145 set = setstr = PRVM_G_STRING( OFS_PARM2 );
3147 out = outstr = VM_GetTempString();
3148 for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
3149 if( *in == '\\' && !*++in )
3151 else if( *in == '\'' )
3154 for( ; *set ; *out++ = *set++ );
3157 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3160 void VM_Cmd_Init(void)
3162 // only init the stuff for the current prog
3163 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3168 void VM_Cmd_Reset(void)
3170 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3171 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3172 memheader_t *header;
3175 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3176 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3179 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3180 CL_PurgeOwner( MENUOWNER );
3182 VM_Files_CloseAll();
3185 //============================================================================
3188 char *vm_sv_extensions =
3191 prvm_builtin_t vm_sv_builtins[] = {
3192 0 // to be consistent with the old vm
3195 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3197 void VM_SV_Cmd_Init(void)
3201 void VM_SV_Cmd_Reset(void)
3205 //============================================================================
3208 char *vm_cl_extensions =
3211 prvm_builtin_t vm_cl_builtins[] = {
3212 0 // to be consistent with the old vm
3215 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3217 void VM_CL_Cmd_Init(void)
3221 void VM_CL_Cmd_Reset(void)
3225 //============================================================================
3228 char *vm_m_extensions =
3235 setmousetarget(float target)
3238 void VM_M_setmousetarget(void)
3240 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3242 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3245 in_client_mouse = false;
3248 in_client_mouse = true;
3251 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3259 float getmousetarget
3262 void VM_M_getmousetarget(void)
3264 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3267 PRVM_G_FLOAT(OFS_RETURN) = 2;
3269 PRVM_G_FLOAT(OFS_RETURN) = 1;
3278 setkeydest(float dest)
3281 void VM_M_setkeydest(void)
3283 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3285 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3289 key_dest = key_game;
3293 key_dest = key_menu;
3297 // key_dest = key_message
3300 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3311 void VM_M_getkeydest(void)
3313 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3315 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3319 PRVM_G_FLOAT(OFS_RETURN) = 0;
3322 PRVM_G_FLOAT(OFS_RETURN) = 2;
3326 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3329 PRVM_G_FLOAT(OFS_RETURN) = 3;
3337 callfunction(...,string function_name)
3341 mfunction_t *PRVM_ED_FindFunction (const char *name);
3342 void VM_M_callfunction(void)
3348 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3350 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3353 PRVM_ERROR("VM_M_callfunction: null string !\n");
3355 VM_CheckEmptyString(s);
3357 func = PRVM_ED_FindFunction(s);
3360 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3361 else if (func->first_statement < 0)
3363 // negative statements are built in functions
3364 int builtinnumber = -func->first_statement;
3365 prog->xfunction->builtinsprofile++;
3366 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3367 prog->builtins[builtinnumber]();
3369 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3374 PRVM_ExecuteProgram(func - prog->functions,"");
3383 float isfunction(string function_name)
3386 mfunction_t *PRVM_ED_FindFunction (const char *name);
3387 void VM_M_isfunction(void)
3392 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3394 s = PRVM_G_STRING(OFS_PARM0);
3397 PRVM_ERROR("VM_M_isfunction: null string !\n");
3399 VM_CheckEmptyString(s);
3401 func = PRVM_ED_FindFunction(s);
3404 PRVM_G_FLOAT(OFS_RETURN) = false;
3406 PRVM_G_FLOAT(OFS_RETURN) = true;
3413 writetofile(float fhandle, entity ent)
3416 void VM_M_writetofile(void)
3421 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3423 filenum = PRVM_G_FLOAT(OFS_PARM0);
3424 if (filenum < 0 || filenum >= MAX_VMFILES)
3426 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3429 if (VM_FILES[filenum] == NULL)
3431 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3435 ent = PRVM_G_EDICT(OFS_PARM1);
3438 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3442 PRVM_ED_Write (VM_FILES[filenum], ent);
3449 vector getresolution(float number)
3452 extern unsigned short video_resolutions[][2];
3453 void VM_M_getresolution(void)
3456 VM_SAFEPARMCOUNT(1, VM_getresolution);
3458 nr = PRVM_G_FLOAT(OFS_PARM0);
3461 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3462 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3463 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3470 string keynumtostring(float keynum)
3473 void VM_M_keynumtostring(void)
3477 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3479 keynum = PRVM_G_FLOAT(OFS_PARM0);
3481 tmp = VM_GetTempString();
3483 strcpy(tmp, Key_KeynumToString(keynum));
3485 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3492 float stringtokeynum(string key)
3495 void VM_M_stringtokeynum( void )
3498 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3500 str = PRVM_G_STRING( OFS_PARM0 );
3502 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3507 VM_M_findkeysforcommand
3509 string findkeysforcommand(string command)
3511 the returned string is an altstring
3514 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3516 void M_FindKeysForCommand(char *command, int *keys);
3517 void VM_M_findkeysforcommand(void)
3523 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3525 cmd = PRVM_G_STRING(OFS_PARM0);
3527 VM_CheckEmptyString(cmd);
3529 (ret = VM_GetTempString())[0] = 0;
3531 M_FindKeysForCommand(cmd, keys);
3533 for(i = 0; i < NUMKEYS; i++)
3534 ret = strcat(ret, va(" \'%i\'", keys[i]));
3536 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3541 VM_M_getserverliststat
3543 float getserverliststat(float type)
3548 0 serverlist_viewcount
3549 1 serverlist_totalcount
3557 void VM_M_getserverliststat( void )
3560 VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
3562 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3564 type = PRVM_G_FLOAT( OFS_PARM0 );
3568 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
3571 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
3573 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3576 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3579 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3582 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3585 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
3588 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
3591 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
3596 ========================
3597 VM_M_resetserverlistmasks
3599 resetserverlistmasks()
3600 ========================
3602 void VM_M_resetserverlistmasks( void )
3604 ServerList_ResetMasks();
3609 ========================
3610 VM_M_setserverlistmaskstring
3612 setserverlistmaskstring(float mask, float fld, string str, float op)
3615 ========================
3617 void VM_M_setserverlistmaskstring( void )
3621 serverlist_mask_t *mask;
3624 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
3625 str = PRVM_G_STRING( OFS_PARM1 );
3627 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
3629 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3630 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3631 mask = &serverlist_andmasks[masknr];
3632 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3633 mask = &serverlist_ormasks[masknr - 512 ];
3635 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
3639 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3643 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3646 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3649 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3652 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3655 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3658 Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
3662 mask->active = true;
3663 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3667 ========================
3668 VM_M_setserverlistmasknumber
3670 setserverlistmasknumber(float mask, float fld, float num, float op)
3674 ========================
3676 void VM_M_setserverlistmasknumber( void )
3679 serverlist_mask_t *mask;
3682 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
3684 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3685 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3686 mask = &serverlist_andmasks[masknr];
3687 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3688 mask = &serverlist_ormasks[masknr - 512 ];
3690 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
3694 number = PRVM_G_FLOAT( OFS_PARM2 );
3695 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3698 case SLIF_MAXPLAYERS:
3699 mask->info.maxplayers = number;
3701 case SLIF_NUMPLAYERS:
3702 mask->info.numplayers = number;
3705 mask->info.ping = number;
3708 mask->info.protocol = number;
3711 Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
3715 mask->active = true;
3716 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3721 ========================
3722 VM_M_resortserverlist
3725 ========================
3727 void VM_M_resortserverlist( void )
3729 ServerList_RebuildViewList();
3734 VM_M_getserverliststring
3736 string getserverliststring(float field, float hostnr)
3739 void VM_M_getserverliststring(void)
3741 serverlist_entry_t *cache;
3744 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3746 PRVM_G_INT(OFS_RETURN) = 0;
3748 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3750 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3752 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3755 cache = serverlist_viewlist[hostnr];
3756 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3758 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3761 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3764 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3767 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3770 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3772 // TODO remove this again
3774 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3777 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3780 Con_Print("VM_M_getserverliststring: bad field number passed!\n");
3786 VM_M_getserverlistnumber
3788 float getserverlistnumber(float field, float hostnr)
3791 void VM_M_getserverlistnumber(void)
3793 serverlist_entry_t *cache;
3796 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3798 PRVM_G_INT(OFS_RETURN) = 0;
3800 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3802 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3804 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3807 cache = serverlist_viewlist[hostnr];
3808 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3809 case SLIF_MAXPLAYERS:
3810 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3812 case SLIF_NUMPLAYERS:
3813 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3816 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3819 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3822 Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
3827 ========================
3828 VM_M_setserverlistsort
3830 setserverlistsort(float field, float descending)
3831 ========================
3833 void VM_M_setserverlistsort( void )
3835 VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
3837 serverlist_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3838 serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3842 ========================
3843 VM_M_refreshserverlist
3846 ========================
3848 void VM_M_refreshserverlist( void )
3850 VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
3851 ServerList_QueryList();
3855 ========================
3856 VM_M_getserverlistindexforkey
3858 float getserverlistindexforkey(string key)
3859 ========================
3861 void VM_M_getserverlistindexforkey( void )
3864 VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
3866 key = PRVM_G_STRING( OFS_PARM0 );
3867 VM_CheckEmptyString( key );
3869 if( !strcmp( key, "cname" ) )
3870 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
3871 else if( !strcmp( key, "ping" ) )
3872 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
3873 else if( !strcmp( key, "game" ) )
3874 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
3875 else if( !strcmp( key, "mod" ) )
3876 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
3877 else if( !strcmp( key, "map" ) )
3878 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
3879 else if( !strcmp( key, "name" ) )
3880 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
3881 else if( !strcmp( key, "maxplayers" ) )
3882 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
3883 else if( !strcmp( key, "numplayers" ) )
3884 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
3885 else if( !strcmp( key, "protocol" ) )
3886 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
3888 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3892 ========================
3893 VM_M_addwantedserverlistkey
3895 addwantedserverlistkey(string key)
3896 ========================
3898 void VM_M_addwantedserverlistkey( void )
3900 VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
3903 prvm_builtin_t vm_m_builtins[] = {
3904 0, // to be consistent with the old vm
3905 // common builtings (mostly)
3982 VM_search_getfilename, // 77
3986 VM_itof, // isString
3991 VM_altstr_ins, // 86
4005 VM_WriteEntity, // 408
4021 VM_drawresetcliparea,
4022 VM_getimagesize,// 460
4027 VM_cin_restart, // 465
4036 VM_M_setmousetarget,
4037 VM_M_getmousetarget,
4042 VM_M_keynumtostring,
4043 VM_M_findkeysforcommand,// 610
4044 VM_M_getserverliststat,
4045 VM_M_getserverliststring,
4046 VM_M_parseentitydata,
4047 VM_M_stringtokeynum,
4048 VM_M_resetserverlistmasks,
4049 VM_M_setserverlistmaskstring,
4050 VM_M_setserverlistmasknumber,
4051 VM_M_resortserverlist,
4052 VM_M_setserverlistsort,
4053 VM_M_refreshserverlist,
4054 VM_M_getserverlistnumber,
4055 VM_M_getserverlistindexforkey,
4056 VM_M_addwantedserverlistkey // 623
4059 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4061 void VM_M_Cmd_Init(void)
4066 void VM_M_Cmd_Reset(void)