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->alias.aliasnum_tags)
2164 for (i = 0;i < model->alias.aliasnum_tags;i++)
2165 if (!strcmp(tagname, model->alias.aliasdata_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;
2256 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
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 if(!Draw_CachePic(s, false))
2580 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2590 void VM_freepic(void)
2594 VM_SAFEPARMCOUNT(1,VM_freepic);
2596 s = PRVM_G_STRING(OFS_PARM0);
2599 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2601 VM_CheckEmptyString (s);
2610 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2613 void VM_drawcharacter(void)
2615 float *pos,*scale,*rgb;
2618 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2620 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2623 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2624 PRVM_G_FLOAT(OFS_RETURN) = -1;
2628 pos = PRVM_G_VECTOR(OFS_PARM0);
2629 scale = PRVM_G_VECTOR(OFS_PARM2);
2630 rgb = PRVM_G_VECTOR(OFS_PARM3);
2631 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2633 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2635 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2636 PRVM_G_FLOAT(OFS_RETURN) = -2;
2640 if(pos[2] || scale[2])
2641 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")));
2643 if(!scale[0] || !scale[1])
2645 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2646 PRVM_G_FLOAT(OFS_RETURN) = -3;
2650 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2651 PRVM_G_FLOAT(OFS_RETURN) = 1;
2658 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2661 void VM_drawstring(void)
2663 float *pos,*scale,*rgb;
2666 VM_SAFEPARMCOUNT(6,VM_drawstring);
2668 string = PRVM_G_STRING(OFS_PARM1);
2671 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2672 PRVM_G_FLOAT(OFS_RETURN) = -1;
2676 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2678 pos = PRVM_G_VECTOR(OFS_PARM0);
2679 scale = PRVM_G_VECTOR(OFS_PARM2);
2680 rgb = PRVM_G_VECTOR(OFS_PARM3);
2681 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2683 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2685 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2686 PRVM_G_FLOAT(OFS_RETURN) = -2;
2690 if(!scale[0] || !scale[1])
2692 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2693 PRVM_G_FLOAT(OFS_RETURN) = -3;
2697 if(pos[2] || scale[2])
2698 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")));
2700 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2701 PRVM_G_FLOAT(OFS_RETURN) = 1;
2707 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2710 void VM_drawpic(void)
2713 float *size, *pos, *rgb;
2716 VM_SAFEPARMCOUNT(6,VM_drawpic);
2718 pic = PRVM_G_STRING(OFS_PARM1);
2722 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2723 PRVM_G_FLOAT(OFS_RETURN) = -1;
2727 VM_CheckEmptyString (pic);
2729 // is pic cached ? no function yet for that
2732 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2733 PRVM_G_FLOAT(OFS_RETURN) = -4;
2737 pos = PRVM_G_VECTOR(OFS_PARM0);
2738 size = PRVM_G_VECTOR(OFS_PARM2);
2739 rgb = PRVM_G_VECTOR(OFS_PARM3);
2740 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2742 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2744 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2745 PRVM_G_FLOAT(OFS_RETURN) = -2;
2749 if(pos[2] || size[2])
2750 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")));
2752 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2753 PRVM_G_FLOAT(OFS_RETURN) = 1;
2760 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2763 void VM_drawfill(void)
2765 float *size, *pos, *rgb;
2768 VM_SAFEPARMCOUNT(5,VM_drawfill);
2771 pos = PRVM_G_VECTOR(OFS_PARM0);
2772 size = PRVM_G_VECTOR(OFS_PARM1);
2773 rgb = PRVM_G_VECTOR(OFS_PARM2);
2774 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2776 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2778 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2779 PRVM_G_FLOAT(OFS_RETURN) = -2;
2783 if(pos[2] || size[2])
2784 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")));
2786 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2787 PRVM_G_FLOAT(OFS_RETURN) = 1;
2794 drawsetcliparea(float x, float y, float width, float height)
2797 void VM_drawsetcliparea(void)
2800 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2802 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2803 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2804 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2805 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2807 DrawQ_SetClipArea(x, y, w, h);
2812 VM_drawresetcliparea
2817 void VM_drawresetcliparea(void)
2819 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2821 DrawQ_ResetClipArea();
2828 vector getimagesize(string pic)
2831 void VM_getimagesize(void)
2836 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2838 p = PRVM_G_STRING(OFS_PARM0);
2841 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2843 VM_CheckEmptyString (p);
2845 pic = Draw_CachePic (p, false);
2847 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2848 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2849 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2852 // CL_Video interface functions
2855 ========================
2858 float cin_open(string file, string name)
2859 ========================
2861 void VM_cin_open( void )
2866 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2868 file = PRVM_G_STRING( OFS_PARM0 );
2869 name = PRVM_G_STRING( OFS_PARM1 );
2871 VM_CheckEmptyString( file );
2872 VM_CheckEmptyString( name );
2874 if( CL_OpenVideo( file, name, MENUOWNER ) )
2875 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2877 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2881 ========================
2884 void cin_close(string name)
2885 ========================
2887 void VM_cin_close( void )
2891 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2893 name = PRVM_G_STRING( OFS_PARM0 );
2894 VM_CheckEmptyString( name );
2896 CL_CloseVideo( CL_GetVideo( name ) );
2900 ========================
2902 void cin_setstate(string name, float type)
2903 ========================
2905 void VM_cin_setstate( void )
2908 clvideostate_t state;
2911 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2913 name = PRVM_G_STRING( OFS_PARM0 );
2914 VM_CheckEmptyString( name );
2916 state = PRVM_G_FLOAT( OFS_PARM1 );
2918 video = CL_GetVideo( name );
2919 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2920 CL_SetVideoState( video, state );
2924 ========================
2927 float cin_getstate(string name)
2928 ========================
2930 void VM_cin_getstate( void )
2935 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2937 name = PRVM_G_STRING( OFS_PARM0 );
2938 VM_CheckEmptyString( name );
2940 video = CL_GetVideo( name );
2942 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2944 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2948 ========================
2951 void cin_restart(string name)
2952 ========================
2954 void VM_cin_restart( void )
2959 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2961 name = PRVM_G_STRING( OFS_PARM0 );
2962 VM_CheckEmptyString( name );
2964 video = CL_GetVideo( name );
2966 CL_RestartVideo( video );
2969 ////////////////////////////////////////
2970 // AltString functions
2971 ////////////////////////////////////////
2974 ========================
2977 float altstr_count(string)
2978 ========================
2980 void VM_altstr_count( void )
2985 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2987 altstr = PRVM_G_STRING( OFS_PARM0 );
2988 //VM_CheckEmptyString( altstr );
2990 for( count = 0, pos = altstr ; *pos ; pos++ )
2991 if( *pos == '\\' && !*++pos )
2993 else if( *pos == '\'' )
2996 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
3000 ========================
3003 string altstr_prepare(string)
3004 ========================
3006 void VM_altstr_prepare( void )
3012 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3014 instr = PRVM_G_STRING( OFS_PARM0 );
3015 //VM_CheckEmptyString( instr );
3016 outstr = VM_GetTempString();
3018 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3027 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3031 ========================
3034 string altstr_get(string, float)
3035 ========================
3037 void VM_altstr_get( void )
3039 char *altstr, *pos, *outstr, *out;
3042 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3044 altstr = PRVM_G_STRING( OFS_PARM0 );
3045 //VM_CheckEmptyString( altstr );
3047 count = PRVM_G_FLOAT( OFS_PARM1 );
3048 count = count * 2 + 1;
3050 for( pos = altstr ; *pos && count ; pos++ )
3051 if( *pos == '\\' && !*++pos )
3053 else if( *pos == '\'' )
3057 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3061 outstr = VM_GetTempString();
3062 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3063 if( *pos == '\\' ) {
3068 } else if( *pos == '\'' )
3074 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3078 ========================
3081 string altstr_set(string altstr, float num, string set)
3082 ========================
3084 void VM_altstr_set( void )
3091 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3093 altstr = PRVM_G_STRING( OFS_PARM0 );
3094 //VM_CheckEmptyString( altstr );
3096 num = PRVM_G_FLOAT( OFS_PARM1 );
3098 str = PRVM_G_STRING( OFS_PARM2 );
3099 //VM_CheckEmptyString( str );
3101 outstr = out = VM_GetTempString();
3102 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3103 if( *in == '\\' && !*++in )
3105 else if( *in == '\'' )
3109 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3113 for( ; *str; *out++ = *str++ );
3114 // now jump over the old contents
3116 if( *in == '\'' || (*in == '\\' && !*++in) )
3120 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3125 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3129 ========================
3132 string altstr_ins(string altstr, float num, string set)
3133 ========================
3135 void VM_altstr_ins(void)
3145 in = instr = PRVM_G_STRING( OFS_PARM0 );
3146 num = PRVM_G_FLOAT( OFS_PARM1 );
3147 set = setstr = PRVM_G_STRING( OFS_PARM2 );
3149 out = outstr = VM_GetTempString();
3150 for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
3151 if( *in == '\\' && !*++in )
3153 else if( *in == '\'' )
3156 for( ; *set ; *out++ = *set++ );
3159 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3162 void VM_Cmd_Init(void)
3164 // only init the stuff for the current prog
3165 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3170 void VM_Cmd_Reset(void)
3172 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3173 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3174 memheader_t *header;
3177 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3178 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3181 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3182 CL_PurgeOwner( MENUOWNER );
3184 VM_Files_CloseAll();
3187 //============================================================================
3190 char *vm_sv_extensions =
3193 prvm_builtin_t vm_sv_builtins[] = {
3194 0 // to be consistent with the old vm
3197 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3199 void VM_SV_Cmd_Init(void)
3203 void VM_SV_Cmd_Reset(void)
3207 //============================================================================
3210 char *vm_cl_extensions =
3213 prvm_builtin_t vm_cl_builtins[] = {
3214 0 // to be consistent with the old vm
3217 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3219 void VM_CL_Cmd_Init(void)
3223 void VM_CL_Cmd_Reset(void)
3227 //============================================================================
3230 char *vm_m_extensions =
3237 setmousetarget(float target)
3240 void VM_M_setmousetarget(void)
3242 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3244 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3247 in_client_mouse = false;
3250 in_client_mouse = true;
3253 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3261 float getmousetarget
3264 void VM_M_getmousetarget(void)
3266 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3269 PRVM_G_FLOAT(OFS_RETURN) = 2;
3271 PRVM_G_FLOAT(OFS_RETURN) = 1;
3280 setkeydest(float dest)
3283 void VM_M_setkeydest(void)
3285 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3287 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3291 key_dest = key_game;
3295 key_dest = key_menu;
3299 // key_dest = key_message
3302 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3313 void VM_M_getkeydest(void)
3315 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3317 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3321 PRVM_G_FLOAT(OFS_RETURN) = 0;
3324 PRVM_G_FLOAT(OFS_RETURN) = 2;
3328 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3331 PRVM_G_FLOAT(OFS_RETURN) = 3;
3339 callfunction(...,string function_name)
3343 mfunction_t *PRVM_ED_FindFunction (const char *name);
3344 void VM_M_callfunction(void)
3350 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3352 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3355 PRVM_ERROR("VM_M_callfunction: null string !\n");
3357 VM_CheckEmptyString(s);
3359 func = PRVM_ED_FindFunction(s);
3362 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3363 else if (func->first_statement < 0)
3365 // negative statements are built in functions
3366 int builtinnumber = -func->first_statement;
3367 prog->xfunction->builtinsprofile++;
3368 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3369 prog->builtins[builtinnumber]();
3371 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3376 PRVM_ExecuteProgram(func - prog->functions,"");
3385 float isfunction(string function_name)
3388 mfunction_t *PRVM_ED_FindFunction (const char *name);
3389 void VM_M_isfunction(void)
3394 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3396 s = PRVM_G_STRING(OFS_PARM0);
3399 PRVM_ERROR("VM_M_isfunction: null string !\n");
3401 VM_CheckEmptyString(s);
3403 func = PRVM_ED_FindFunction(s);
3406 PRVM_G_FLOAT(OFS_RETURN) = false;
3408 PRVM_G_FLOAT(OFS_RETURN) = true;
3415 writetofile(float fhandle, entity ent)
3418 void VM_M_writetofile(void)
3423 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3425 filenum = PRVM_G_FLOAT(OFS_PARM0);
3426 if (filenum < 0 || filenum >= MAX_VMFILES)
3428 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3431 if (VM_FILES[filenum] == NULL)
3433 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3437 ent = PRVM_G_EDICT(OFS_PARM1);
3440 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3444 PRVM_ED_Write (VM_FILES[filenum], ent);
3451 vector getresolution(float number)
3454 extern unsigned short video_resolutions[][2];
3455 void VM_M_getresolution(void)
3458 VM_SAFEPARMCOUNT(1, VM_getresolution);
3460 nr = PRVM_G_FLOAT(OFS_PARM0);
3463 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3464 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3465 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3472 string keynumtostring(float keynum)
3475 void VM_M_keynumtostring(void)
3479 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3481 keynum = PRVM_G_FLOAT(OFS_PARM0);
3483 tmp = VM_GetTempString();
3485 strcpy(tmp, Key_KeynumToString(keynum));
3487 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3494 float stringtokeynum(string key)
3497 void VM_M_stringtokeynum( void )
3500 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3502 str = PRVM_G_STRING( OFS_PARM0 );
3504 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3509 VM_M_findkeysforcommand
3511 string findkeysforcommand(string command)
3513 the returned string is an altstring
3516 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3518 void M_FindKeysForCommand(char *command, int *keys);
3519 void VM_M_findkeysforcommand(void)
3525 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3527 cmd = PRVM_G_STRING(OFS_PARM0);
3529 VM_CheckEmptyString(cmd);
3531 (ret = VM_GetTempString())[0] = 0;
3533 M_FindKeysForCommand(cmd, keys);
3535 for(i = 0; i < NUMKEYS; i++)
3536 ret = strcat(ret, va(" \'%i\'", keys[i]));
3538 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3543 VM_M_getserverliststat
3545 float getserverliststat(float type)
3550 0 serverlist_viewcount
3551 1 serverlist_totalcount
3559 void VM_M_getserverliststat( void )
3562 VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
3564 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3566 type = PRVM_G_FLOAT( OFS_PARM0 );
3570 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
3573 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
3575 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3578 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3581 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3584 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3587 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
3590 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
3593 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
3598 ========================
3599 VM_M_resetserverlistmasks
3601 resetserverlistmasks()
3602 ========================
3604 void VM_M_resetserverlistmasks( void )
3606 ServerList_ResetMasks();
3611 ========================
3612 VM_M_setserverlistmaskstring
3614 setserverlistmaskstring(float mask, float fld, string str, float op)
3617 ========================
3619 void VM_M_setserverlistmaskstring( void )
3623 serverlist_mask_t *mask;
3626 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
3627 str = PRVM_G_STRING( OFS_PARM1 );
3629 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
3631 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3632 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3633 mask = &serverlist_andmasks[masknr];
3634 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3635 mask = &serverlist_ormasks[masknr - 512 ];
3637 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
3641 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3645 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3648 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3651 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3654 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3657 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3660 Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
3664 mask->active = true;
3665 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3669 ========================
3670 VM_M_setserverlistmasknumber
3672 setserverlistmasknumber(float mask, float fld, float num, float op)
3676 ========================
3678 void VM_M_setserverlistmasknumber( void )
3681 serverlist_mask_t *mask;
3684 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
3686 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3687 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3688 mask = &serverlist_andmasks[masknr];
3689 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3690 mask = &serverlist_ormasks[masknr - 512 ];
3692 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
3696 number = PRVM_G_FLOAT( OFS_PARM2 );
3697 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3700 case SLIF_MAXPLAYERS:
3701 mask->info.maxplayers = number;
3703 case SLIF_NUMPLAYERS:
3704 mask->info.numplayers = number;
3707 mask->info.ping = number;
3710 mask->info.protocol = number;
3713 Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
3717 mask->active = true;
3718 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3723 ========================
3724 VM_M_resortserverlist
3727 ========================
3729 void VM_M_resortserverlist( void )
3731 ServerList_RebuildViewList();
3736 VM_M_getserverliststring
3738 string getserverliststring(float field, float hostnr)
3741 void VM_M_getserverliststring(void)
3743 serverlist_entry_t *cache;
3746 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3748 PRVM_G_INT(OFS_RETURN) = 0;
3750 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3752 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3754 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3757 cache = serverlist_viewlist[hostnr];
3758 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3760 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3763 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3766 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3769 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3772 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3774 // TODO remove this again
3776 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3779 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3782 Con_Print("VM_M_getserverliststring: bad field number passed!\n");
3788 VM_M_getserverlistnumber
3790 float getserverlistnumber(float field, float hostnr)
3793 void VM_M_getserverlistnumber(void)
3795 serverlist_entry_t *cache;
3798 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3800 PRVM_G_INT(OFS_RETURN) = 0;
3802 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3804 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3806 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3809 cache = serverlist_viewlist[hostnr];
3810 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3811 case SLIF_MAXPLAYERS:
3812 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3814 case SLIF_NUMPLAYERS:
3815 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3818 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3821 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3824 Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
3829 ========================
3830 VM_M_setserverlistsort
3832 setserverlistsort(float field, float descending)
3833 ========================
3835 void VM_M_setserverlistsort( void )
3837 VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
3839 serverlist_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3840 serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3844 ========================
3845 VM_M_refreshserverlist
3848 ========================
3850 void VM_M_refreshserverlist( void )
3852 VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
3853 ServerList_QueryList();
3857 ========================
3858 VM_M_getserverlistindexforkey
3860 float getserverlistindexforkey(string key)
3861 ========================
3863 void VM_M_getserverlistindexforkey( void )
3866 VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
3868 key = PRVM_G_STRING( OFS_PARM0 );
3869 VM_CheckEmptyString( key );
3871 if( !strcmp( key, "cname" ) )
3872 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
3873 else if( !strcmp( key, "ping" ) )
3874 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
3875 else if( !strcmp( key, "game" ) )
3876 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
3877 else if( !strcmp( key, "mod" ) )
3878 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
3879 else if( !strcmp( key, "map" ) )
3880 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
3881 else if( !strcmp( key, "name" ) )
3882 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
3883 else if( !strcmp( key, "maxplayers" ) )
3884 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
3885 else if( !strcmp( key, "numplayers" ) )
3886 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
3887 else if( !strcmp( key, "protocol" ) )
3888 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
3890 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3894 ========================
3895 VM_M_addwantedserverlistkey
3897 addwantedserverlistkey(string key)
3898 ========================
3900 void VM_M_addwantedserverlistkey( void )
3902 VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
3905 prvm_builtin_t vm_m_builtins[] = {
3906 0, // to be consistent with the old vm
3907 // common builtings (mostly)
3984 VM_search_getfilename, // 77
3988 VM_itof, // isString
3993 VM_altstr_ins, // 86
4007 VM_WriteEntity, // 408
4023 VM_drawresetcliparea,
4024 VM_getimagesize,// 460
4029 VM_cin_restart, // 465
4038 VM_M_setmousetarget,
4039 VM_M_getmousetarget,
4044 VM_M_keynumtostring,
4045 VM_M_findkeysforcommand,// 610
4046 VM_M_getserverliststat,
4047 VM_M_getserverliststring,
4048 VM_M_parseentitydata,
4049 VM_M_stringtokeynum,
4050 VM_M_resetserverlistmasks,
4051 VM_M_setserverlistmaskstring,
4052 VM_M_setserverlistmasknumber,
4053 VM_M_resortserverlist,
4054 VM_M_setserverlistsort,
4055 VM_M_refreshserverlist,
4056 VM_M_getserverlistnumber,
4057 VM_M_getserverlistindexforkey,
4058 VM_M_addwantedserverlistkey // 623
4061 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4063 void VM_M_Cmd_Init(void)
4068 void VM_M_Cmd_Reset(void)