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);
2029 PRVM_ERROR( "VM_strunzone: s%: Null string passed!", PRVM_NAME );
2030 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2031 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2038 VM_command (used by client and menu)
2040 clientcommand(float client, string s) (for client and menu)
2043 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2044 //this function originally written by KrimZon, made shorter by LordHavoc
2045 void VM_clcommand (void)
2047 client_t *temp_client;
2050 VM_SAFEPARMCOUNT(2,VM_clcommand);
2052 i = PRVM_G_FLOAT(OFS_PARM0);
2053 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2055 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2059 temp_client = host_client;
2060 host_client = svs.clients + i;
2061 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2062 host_client = temp_client;
2070 float tokenize(string s)
2073 //float(string s) tokenize = #441;
2074 // takes apart a string into individal words (access them with argv), returns how many
2075 // this function originally written by KrimZon, made shorter by LordHavoc
2076 static char **tokens = NULL;
2077 static int max_tokens, num_tokens = 0;
2078 void VM_tokenize (void)
2083 VM_SAFEPARMCOUNT(1,VM_tokenize);
2085 str = PRVM_G_STRING(OFS_PARM0);
2090 for (i=0;i<num_tokens;i++)
2096 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2097 max_tokens = strlen(str);
2099 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2101 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2102 strcpy(tokens[num_tokens], com_token);
2105 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2112 string argv(float n)
2115 //string(float n) argv = #442;
2116 // returns a word from the tokenized string (returns nothing for an invalid index)
2117 // this function originally written by KrimZon, made shorter by LordHavoc
2122 VM_SAFEPARMCOUNT(1,VM_argv);
2124 token_num = PRVM_G_FLOAT(OFS_PARM0);
2125 if (token_num >= 0 && token_num < num_tokens)
2126 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2128 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2132 //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)
2133 void PF_setattachment (void)
2135 edict_t *e = G_EDICT(OFS_PARM0);
2136 edict_t *tagentity = G_EDICT(OFS_PARM1);
2137 char *tagname = G_STRING(OFS_PARM2);
2142 if (tagentity == NULL)
2143 tagentity = sv.edicts;
2145 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2147 v->edict = EDICT_TO_PROG(tagentity);
2149 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2152 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2154 modelindex = (int)tagentity->v->modelindex;
2155 if (modelindex >= 0 && modelindex < MAX_MODELS)
2157 model = sv.models[modelindex];
2158 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2159 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2160 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2162 // FIXME: use a model function to get tag info (need to handle skeletal)
2163 if (v->_float == 0 && model->num_tags)
2164 for (i = 0;i < model->num_tags;i++)
2165 if (!strcmp(tagname, model->data_tags[i].name))
2168 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);
2171 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));
2182 void VM_isserver(void)
2184 VM_SAFEPARMCOUNT(0,VM_serverstate);
2186 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2196 void VM_clientcount(void)
2198 VM_SAFEPARMCOUNT(0,VM_clientcount);
2200 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2210 void VM_clientstate(void)
2212 VM_SAFEPARMCOUNT(0,VM_clientstate);
2214 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2221 float getostype(void)
2223 */ // not used at the moment -> not included in the common list
2224 void VM_getostype(void)
2226 VM_SAFEPARMCOUNT(0,VM_getostype);
2231 OS_MAC - not supported
2235 PRVM_G_FLOAT(OFS_RETURN) = 0;
2237 PRVM_G_FLOAT(OFS_RETURN) = 2;
2239 PRVM_G_FLOAT(OFS_RETURN) = 1;
2247 vector getmousepos()
2250 void VM_getmousepos(void)
2253 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2255 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x * vid.conwidth / vid.realwidth;
2256 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y * vid.conheight / vid.realheight;
2257 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2267 void VM_gettime(void)
2269 VM_SAFEPARMCOUNT(0,VM_gettime);
2271 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2278 loadfromdata(string data)
2281 void VM_loadfromdata(void)
2283 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2285 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2289 ========================
2290 VM_M_parseentitydata
2292 parseentitydata(entity ent, string data)
2293 ========================
2295 void VM_M_parseentitydata(void)
2300 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2302 // get edict and test it
2303 ent = PRVM_G_EDICT(OFS_PARM0);
2305 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2307 data = PRVM_G_STRING(OFS_PARM1);
2309 // parse the opening brace
2310 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2311 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2313 PRVM_ED_ParseEdict (data, ent);
2320 loadfromfile(string file)
2323 void VM_loadfromfile(void)
2328 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2330 filename = PRVM_G_STRING(OFS_PARM0);
2331 // .. is parent directory on many platforms
2332 // / is parent directory on Amiga
2333 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2334 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2335 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2337 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2338 PRVM_G_FLOAT(OFS_RETURN) = -4;
2342 // not conform with VM_fopen
2343 data = FS_LoadFile(filename, tempmempool, false);
2345 PRVM_G_FLOAT(OFS_RETURN) = -1;
2347 PRVM_ED_LoadFromFile(data);
2358 float mod(float val, float m)
2361 void VM_modulo(void)
2364 VM_SAFEPARMCOUNT(2,VM_module);
2366 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2367 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2369 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2372 void VM_Search_Init(void)
2374 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2377 void VM_Search_Reset(void)
2380 // reset the fssearch list
2381 for(i = 0; i < MAX_VMSEARCHES; i++)
2382 if(VM_SEARCHLIST[i])
2383 FS_FreeSearch(VM_SEARCHLIST[i]);
2384 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2391 float search_begin(string pattern, float caseinsensitive, float quiet)
2394 void VM_search_begin(void)
2398 int caseinsens, quiet;
2400 VM_SAFEPARMCOUNT(3, VM_search_begin);
2402 pattern = PRVM_G_STRING(OFS_PARM0);
2404 VM_CheckEmptyString(pattern);
2406 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2407 quiet = PRVM_G_FLOAT(OFS_PARM2);
2409 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2410 if(!VM_SEARCHLIST[handle])
2413 if(handle >= MAX_VMSEARCHES)
2415 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2416 PRVM_G_FLOAT(OFS_RETURN) = -2;
2420 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2421 PRVM_G_FLOAT(OFS_RETURN) = -1;
2423 PRVM_G_FLOAT(OFS_RETURN) = handle;
2430 void search_end(float handle)
2433 void VM_search_end(void)
2436 VM_SAFEPARMCOUNT(1, VM_search_end);
2438 handle = PRVM_G_FLOAT(OFS_PARM0);
2440 if(handle < 0 || handle >= MAX_VMSEARCHES)
2442 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2445 if(VM_SEARCHLIST[handle] == NULL)
2447 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2451 FS_FreeSearch(VM_SEARCHLIST[handle]);
2452 VM_SEARCHLIST[handle] = NULL;
2459 float search_getsize(float handle)
2462 void VM_search_getsize(void)
2465 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2467 handle = PRVM_G_FLOAT(OFS_PARM0);
2469 if(handle < 0 || handle >= MAX_VMSEARCHES)
2471 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2474 if(VM_SEARCHLIST[handle] == NULL)
2476 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2480 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2485 VM_search_getfilename
2487 string search_getfilename(float handle, float num)
2490 void VM_search_getfilename(void)
2492 int handle, filenum;
2494 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2496 handle = PRVM_G_FLOAT(OFS_PARM0);
2497 filenum = PRVM_G_FLOAT(OFS_PARM1);
2499 if(handle < 0 || handle >= MAX_VMSEARCHES)
2501 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2504 if(VM_SEARCHLIST[handle] == NULL)
2506 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2509 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2511 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2515 tmp = VM_GetTempString();
2516 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2518 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2525 string chr(float ascii)
2531 VM_SAFEPARMCOUNT(1, VM_chr);
2533 tmp = VM_GetTempString();
2534 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2537 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2540 //=============================================================================
2541 // Draw builtins (client & menu)
2547 float iscachedpic(string pic)
2550 void VM_iscachedpic(void)
2552 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2554 // drawq hasnt such a function, thus always return true
2555 PRVM_G_FLOAT(OFS_RETURN) = false;
2562 string precache_pic(string pic)
2565 void VM_precache_pic(void)
2569 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2571 s = PRVM_G_STRING(OFS_PARM0);
2572 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2575 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2577 VM_CheckEmptyString (s);
2579 // AK Draw_CachePic is supposed to always return a valid pointer
2580 if( Draw_CachePic(s, false)->tex == r_texture_notexture )
2581 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2591 void VM_freepic(void)
2595 VM_SAFEPARMCOUNT(1,VM_freepic);
2597 s = PRVM_G_STRING(OFS_PARM0);
2600 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2602 VM_CheckEmptyString (s);
2611 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2614 void VM_drawcharacter(void)
2616 float *pos,*scale,*rgb;
2619 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2621 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2624 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2625 PRVM_G_FLOAT(OFS_RETURN) = -1;
2629 pos = PRVM_G_VECTOR(OFS_PARM0);
2630 scale = PRVM_G_VECTOR(OFS_PARM2);
2631 rgb = PRVM_G_VECTOR(OFS_PARM3);
2632 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2634 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2636 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2637 PRVM_G_FLOAT(OFS_RETURN) = -2;
2641 if(pos[2] || scale[2])
2642 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")));
2644 if(!scale[0] || !scale[1])
2646 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2647 PRVM_G_FLOAT(OFS_RETURN) = -3;
2651 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2652 PRVM_G_FLOAT(OFS_RETURN) = 1;
2659 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2662 void VM_drawstring(void)
2664 float *pos,*scale,*rgb;
2667 VM_SAFEPARMCOUNT(6,VM_drawstring);
2669 string = PRVM_G_STRING(OFS_PARM1);
2672 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2673 PRVM_G_FLOAT(OFS_RETURN) = -1;
2677 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2679 pos = PRVM_G_VECTOR(OFS_PARM0);
2680 scale = PRVM_G_VECTOR(OFS_PARM2);
2681 rgb = PRVM_G_VECTOR(OFS_PARM3);
2682 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2684 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2686 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2687 PRVM_G_FLOAT(OFS_RETURN) = -2;
2691 if(!scale[0] || !scale[1])
2693 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2694 PRVM_G_FLOAT(OFS_RETURN) = -3;
2698 if(pos[2] || scale[2])
2699 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")));
2701 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2702 PRVM_G_FLOAT(OFS_RETURN) = 1;
2708 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2711 void VM_drawpic(void)
2714 float *size, *pos, *rgb;
2717 VM_SAFEPARMCOUNT(6,VM_drawpic);
2719 pic = PRVM_G_STRING(OFS_PARM1);
2723 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2724 PRVM_G_FLOAT(OFS_RETURN) = -1;
2728 VM_CheckEmptyString (pic);
2730 // is pic cached ? no function yet for that
2733 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2734 PRVM_G_FLOAT(OFS_RETURN) = -4;
2738 pos = PRVM_G_VECTOR(OFS_PARM0);
2739 size = PRVM_G_VECTOR(OFS_PARM2);
2740 rgb = PRVM_G_VECTOR(OFS_PARM3);
2741 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2743 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2745 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2746 PRVM_G_FLOAT(OFS_RETURN) = -2;
2750 if(pos[2] || size[2])
2751 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")));
2753 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2754 PRVM_G_FLOAT(OFS_RETURN) = 1;
2761 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2764 void VM_drawfill(void)
2766 float *size, *pos, *rgb;
2769 VM_SAFEPARMCOUNT(5,VM_drawfill);
2772 pos = PRVM_G_VECTOR(OFS_PARM0);
2773 size = PRVM_G_VECTOR(OFS_PARM1);
2774 rgb = PRVM_G_VECTOR(OFS_PARM2);
2775 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2777 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2779 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2780 PRVM_G_FLOAT(OFS_RETURN) = -2;
2784 if(pos[2] || size[2])
2785 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")));
2787 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2788 PRVM_G_FLOAT(OFS_RETURN) = 1;
2795 drawsetcliparea(float x, float y, float width, float height)
2798 void VM_drawsetcliparea(void)
2801 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2803 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2804 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2805 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2806 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2808 DrawQ_SetClipArea(x, y, w, h);
2813 VM_drawresetcliparea
2818 void VM_drawresetcliparea(void)
2820 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2822 DrawQ_ResetClipArea();
2829 vector getimagesize(string pic)
2832 void VM_getimagesize(void)
2837 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2839 p = PRVM_G_STRING(OFS_PARM0);
2842 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2844 VM_CheckEmptyString (p);
2846 pic = Draw_CachePic (p, false);
2848 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2849 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2850 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2853 // CL_Video interface functions
2856 ========================
2859 float cin_open(string file, string name)
2860 ========================
2862 void VM_cin_open( void )
2867 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2869 file = PRVM_G_STRING( OFS_PARM0 );
2870 name = PRVM_G_STRING( OFS_PARM1 );
2872 VM_CheckEmptyString( file );
2873 VM_CheckEmptyString( name );
2875 if( CL_OpenVideo( file, name, MENUOWNER ) )
2876 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2878 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2882 ========================
2885 void cin_close(string name)
2886 ========================
2888 void VM_cin_close( void )
2892 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2894 name = PRVM_G_STRING( OFS_PARM0 );
2895 VM_CheckEmptyString( name );
2897 CL_CloseVideo( CL_GetVideo( name ) );
2901 ========================
2903 void cin_setstate(string name, float type)
2904 ========================
2906 void VM_cin_setstate( void )
2909 clvideostate_t state;
2912 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2914 name = PRVM_G_STRING( OFS_PARM0 );
2915 VM_CheckEmptyString( name );
2917 state = PRVM_G_FLOAT( OFS_PARM1 );
2919 video = CL_GetVideo( name );
2920 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2921 CL_SetVideoState( video, state );
2925 ========================
2928 float cin_getstate(string name)
2929 ========================
2931 void VM_cin_getstate( void )
2936 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2938 name = PRVM_G_STRING( OFS_PARM0 );
2939 VM_CheckEmptyString( name );
2941 video = CL_GetVideo( name );
2943 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2945 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2949 ========================
2952 void cin_restart(string name)
2953 ========================
2955 void VM_cin_restart( void )
2960 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2962 name = PRVM_G_STRING( OFS_PARM0 );
2963 VM_CheckEmptyString( name );
2965 video = CL_GetVideo( name );
2967 CL_RestartVideo( video );
2970 ////////////////////////////////////////
2971 // AltString functions
2972 ////////////////////////////////////////
2975 ========================
2978 float altstr_count(string)
2979 ========================
2981 void VM_altstr_count( void )
2986 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2988 altstr = PRVM_G_STRING( OFS_PARM0 );
2989 //VM_CheckEmptyString( altstr );
2991 for( count = 0, pos = altstr ; *pos ; pos++ )
2992 if( *pos == '\\' && !*++pos )
2994 else if( *pos == '\'' )
2997 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
3001 ========================
3004 string altstr_prepare(string)
3005 ========================
3007 void VM_altstr_prepare( void )
3013 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3015 instr = PRVM_G_STRING( OFS_PARM0 );
3016 //VM_CheckEmptyString( instr );
3017 outstr = VM_GetTempString();
3019 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3028 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3032 ========================
3035 string altstr_get(string, float)
3036 ========================
3038 void VM_altstr_get( void )
3040 char *altstr, *pos, *outstr, *out;
3043 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3045 altstr = PRVM_G_STRING( OFS_PARM0 );
3046 //VM_CheckEmptyString( altstr );
3048 count = PRVM_G_FLOAT( OFS_PARM1 );
3049 count = count * 2 + 1;
3051 for( pos = altstr ; *pos && count ; pos++ )
3052 if( *pos == '\\' && !*++pos )
3054 else if( *pos == '\'' )
3058 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3062 outstr = VM_GetTempString();
3063 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3064 if( *pos == '\\' ) {
3069 } else if( *pos == '\'' )
3075 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3079 ========================
3082 string altstr_set(string altstr, float num, string set)
3083 ========================
3085 void VM_altstr_set( void )
3092 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3094 altstr = PRVM_G_STRING( OFS_PARM0 );
3095 //VM_CheckEmptyString( altstr );
3097 num = PRVM_G_FLOAT( OFS_PARM1 );
3099 str = PRVM_G_STRING( OFS_PARM2 );
3100 //VM_CheckEmptyString( str );
3102 outstr = out = VM_GetTempString();
3103 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3104 if( *in == '\\' && !*++in )
3106 else if( *in == '\'' )
3110 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3114 for( ; *str; *out++ = *str++ );
3115 // now jump over the old contents
3117 if( *in == '\'' || (*in == '\\' && !*++in) )
3121 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3126 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3130 ========================
3133 string altstr_ins(string altstr, float num, string set)
3134 ========================
3136 void VM_altstr_ins(void)
3146 in = instr = PRVM_G_STRING( OFS_PARM0 );
3147 num = PRVM_G_FLOAT( OFS_PARM1 );
3148 set = setstr = PRVM_G_STRING( OFS_PARM2 );
3150 out = outstr = VM_GetTempString();
3151 for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
3152 if( *in == '\\' && !*++in )
3154 else if( *in == '\'' )
3157 for( ; *set ; *out++ = *set++ );
3160 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3163 void VM_Cmd_Init(void)
3165 // only init the stuff for the current prog
3166 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3171 void VM_Cmd_Reset(void)
3173 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3174 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3175 memheader_t *header;
3178 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3179 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3182 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3183 CL_PurgeOwner( MENUOWNER );
3185 VM_Files_CloseAll();
3188 //============================================================================
3191 char *vm_sv_extensions =
3194 prvm_builtin_t vm_sv_builtins[] = {
3195 0 // to be consistent with the old vm
3198 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3200 void VM_SV_Cmd_Init(void)
3204 void VM_SV_Cmd_Reset(void)
3208 //============================================================================
3211 char *vm_cl_extensions =
3214 prvm_builtin_t vm_cl_builtins[] = {
3215 0 // to be consistent with the old vm
3218 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3220 void VM_CL_Cmd_Init(void)
3224 void VM_CL_Cmd_Reset(void)
3228 //============================================================================
3231 char *vm_m_extensions =
3238 setmousetarget(float target)
3241 void VM_M_setmousetarget(void)
3243 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3245 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3248 in_client_mouse = false;
3251 in_client_mouse = true;
3254 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3262 float getmousetarget
3265 void VM_M_getmousetarget(void)
3267 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3270 PRVM_G_FLOAT(OFS_RETURN) = 2;
3272 PRVM_G_FLOAT(OFS_RETURN) = 1;
3281 setkeydest(float dest)
3284 void VM_M_setkeydest(void)
3286 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3288 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3292 key_dest = key_game;
3296 key_dest = key_menu;
3300 // key_dest = key_message
3303 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3314 void VM_M_getkeydest(void)
3316 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3318 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3322 PRVM_G_FLOAT(OFS_RETURN) = 0;
3325 PRVM_G_FLOAT(OFS_RETURN) = 2;
3329 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3332 PRVM_G_FLOAT(OFS_RETURN) = 3;
3340 callfunction(...,string function_name)
3344 mfunction_t *PRVM_ED_FindFunction (const char *name);
3345 void VM_M_callfunction(void)
3351 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3353 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3356 PRVM_ERROR("VM_M_callfunction: null string !\n");
3358 VM_CheckEmptyString(s);
3360 func = PRVM_ED_FindFunction(s);
3363 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3364 else if (func->first_statement < 0)
3366 // negative statements are built in functions
3367 int builtinnumber = -func->first_statement;
3368 prog->xfunction->builtinsprofile++;
3369 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3370 prog->builtins[builtinnumber]();
3372 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3377 PRVM_ExecuteProgram(func - prog->functions,"");
3386 float isfunction(string function_name)
3389 mfunction_t *PRVM_ED_FindFunction (const char *name);
3390 void VM_M_isfunction(void)
3395 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3397 s = PRVM_G_STRING(OFS_PARM0);
3400 PRVM_ERROR("VM_M_isfunction: null string !\n");
3402 VM_CheckEmptyString(s);
3404 func = PRVM_ED_FindFunction(s);
3407 PRVM_G_FLOAT(OFS_RETURN) = false;
3409 PRVM_G_FLOAT(OFS_RETURN) = true;
3416 writetofile(float fhandle, entity ent)
3419 void VM_M_writetofile(void)
3424 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3426 filenum = PRVM_G_FLOAT(OFS_PARM0);
3427 if (filenum < 0 || filenum >= MAX_VMFILES)
3429 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3432 if (VM_FILES[filenum] == NULL)
3434 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3438 ent = PRVM_G_EDICT(OFS_PARM1);
3441 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3445 PRVM_ED_Write (VM_FILES[filenum], ent);
3452 vector getresolution(float number)
3455 extern unsigned short video_resolutions[][2];
3456 void VM_M_getresolution(void)
3459 VM_SAFEPARMCOUNT(1, VM_getresolution);
3461 nr = PRVM_G_FLOAT(OFS_PARM0);
3464 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3465 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3466 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3473 string keynumtostring(float keynum)
3476 void VM_M_keynumtostring(void)
3480 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3482 keynum = PRVM_G_FLOAT(OFS_PARM0);
3484 tmp = VM_GetTempString();
3486 strcpy(tmp, Key_KeynumToString(keynum));
3488 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3495 float stringtokeynum(string key)
3498 void VM_M_stringtokeynum( void )
3501 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3503 str = PRVM_G_STRING( OFS_PARM0 );
3505 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3510 VM_M_findkeysforcommand
3512 string findkeysforcommand(string command)
3514 the returned string is an altstring
3517 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3519 void M_FindKeysForCommand(char *command, int *keys);
3520 void VM_M_findkeysforcommand(void)
3526 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3528 cmd = PRVM_G_STRING(OFS_PARM0);
3530 VM_CheckEmptyString(cmd);
3532 (ret = VM_GetTempString())[0] = 0;
3534 M_FindKeysForCommand(cmd, keys);
3536 for(i = 0; i < NUMKEYS; i++)
3537 ret = strcat(ret, va(" \'%i\'", keys[i]));
3539 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3544 VM_M_getserverliststat
3546 float getserverliststat(float type)
3551 0 serverlist_viewcount
3552 1 serverlist_totalcount
3560 void VM_M_getserverliststat( void )
3563 VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
3565 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3567 type = PRVM_G_FLOAT( OFS_PARM0 );
3571 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
3574 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
3576 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3579 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3582 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3585 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3588 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
3591 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
3594 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
3599 ========================
3600 VM_M_resetserverlistmasks
3602 resetserverlistmasks()
3603 ========================
3605 void VM_M_resetserverlistmasks( void )
3607 ServerList_ResetMasks();
3612 ========================
3613 VM_M_setserverlistmaskstring
3615 setserverlistmaskstring(float mask, float fld, string str, float op)
3618 ========================
3620 void VM_M_setserverlistmaskstring( void )
3624 serverlist_mask_t *mask;
3627 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
3628 str = PRVM_G_STRING( OFS_PARM1 );
3630 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
3632 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3633 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3634 mask = &serverlist_andmasks[masknr];
3635 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3636 mask = &serverlist_ormasks[masknr - 512 ];
3638 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
3642 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3646 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3649 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3652 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3655 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3658 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3661 Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
3665 mask->active = true;
3666 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3670 ========================
3671 VM_M_setserverlistmasknumber
3673 setserverlistmasknumber(float mask, float fld, float num, float op)
3677 ========================
3679 void VM_M_setserverlistmasknumber( void )
3682 serverlist_mask_t *mask;
3685 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
3687 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3688 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3689 mask = &serverlist_andmasks[masknr];
3690 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3691 mask = &serverlist_ormasks[masknr - 512 ];
3693 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
3697 number = PRVM_G_FLOAT( OFS_PARM2 );
3698 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3701 case SLIF_MAXPLAYERS:
3702 mask->info.maxplayers = number;
3704 case SLIF_NUMPLAYERS:
3705 mask->info.numplayers = number;
3708 mask->info.ping = number;
3711 mask->info.protocol = number;
3714 Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
3718 mask->active = true;
3719 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3724 ========================
3725 VM_M_resortserverlist
3728 ========================
3730 void VM_M_resortserverlist( void )
3732 ServerList_RebuildViewList();
3737 VM_M_getserverliststring
3739 string getserverliststring(float field, float hostnr)
3742 void VM_M_getserverliststring(void)
3744 serverlist_entry_t *cache;
3747 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3749 PRVM_G_INT(OFS_RETURN) = 0;
3751 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3753 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3755 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3758 cache = serverlist_viewlist[hostnr];
3759 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3761 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3764 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3767 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3770 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3773 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3775 // TODO remove this again
3777 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3780 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3783 Con_Print("VM_M_getserverliststring: bad field number passed!\n");
3789 VM_M_getserverlistnumber
3791 float getserverlistnumber(float field, float hostnr)
3794 void VM_M_getserverlistnumber(void)
3796 serverlist_entry_t *cache;
3799 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3801 PRVM_G_INT(OFS_RETURN) = 0;
3803 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3805 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3807 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3810 cache = serverlist_viewlist[hostnr];
3811 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3812 case SLIF_MAXPLAYERS:
3813 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3815 case SLIF_NUMPLAYERS:
3816 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3819 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3822 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3825 Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
3830 ========================
3831 VM_M_setserverlistsort
3833 setserverlistsort(float field, float descending)
3834 ========================
3836 void VM_M_setserverlistsort( void )
3838 VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
3840 serverlist_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3841 serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3845 ========================
3846 VM_M_refreshserverlist
3849 ========================
3851 void VM_M_refreshserverlist( void )
3853 VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
3854 ServerList_QueryList();
3858 ========================
3859 VM_M_getserverlistindexforkey
3861 float getserverlistindexforkey(string key)
3862 ========================
3864 void VM_M_getserverlistindexforkey( void )
3867 VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
3869 key = PRVM_G_STRING( OFS_PARM0 );
3870 VM_CheckEmptyString( key );
3872 if( !strcmp( key, "cname" ) )
3873 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
3874 else if( !strcmp( key, "ping" ) )
3875 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
3876 else if( !strcmp( key, "game" ) )
3877 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
3878 else if( !strcmp( key, "mod" ) )
3879 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
3880 else if( !strcmp( key, "map" ) )
3881 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
3882 else if( !strcmp( key, "name" ) )
3883 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
3884 else if( !strcmp( key, "maxplayers" ) )
3885 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
3886 else if( !strcmp( key, "numplayers" ) )
3887 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
3888 else if( !strcmp( key, "protocol" ) )
3889 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
3891 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3895 ========================
3896 VM_M_addwantedserverlistkey
3898 addwantedserverlistkey(string key)
3899 ========================
3901 void VM_M_addwantedserverlistkey( void )
3903 VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
3906 prvm_builtin_t vm_m_builtins[] = {
3907 0, // to be consistent with the old vm
3908 // common builtings (mostly)
3985 VM_search_getfilename, // 77
3989 VM_itof, // isString
3994 VM_altstr_ins, // 86
4008 VM_WriteEntity, // 408
4024 VM_drawresetcliparea,
4025 VM_getimagesize,// 460
4030 VM_cin_restart, // 465
4039 VM_M_setmousetarget,
4040 VM_M_getmousetarget,
4045 VM_M_keynumtostring,
4046 VM_M_findkeysforcommand,// 610
4047 VM_M_getserverliststat,
4048 VM_M_getserverliststring,
4049 VM_M_parseentitydata,
4050 VM_M_stringtokeynum,
4051 VM_M_resetserverlistmasks,
4052 VM_M_setserverlistmaskstring,
4053 VM_M_setserverlistmasknumber,
4054 VM_M_resortserverlist,
4055 VM_M_setserverlistsort,
4056 VM_M_refreshserverlist,
4057 VM_M_getserverlistnumber,
4058 VM_M_getserverlistindexforkey,
4059 VM_M_addwantedserverlistkey // 623
4062 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4064 void VM_M_Cmd_Init(void)
4069 void VM_M_Cmd_Reset(void)