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 perhaps only : Menu : WriteMsg
104 ===============================
106 WriteByte(float data, float dest, float desto)
107 WriteChar(float data, float dest, float desto)
108 WriteShort(float data, float dest, float desto)
109 WriteLong(float data, float dest, float desto)
110 WriteAngle(float data, float dest, float desto)
111 WriteCoord(float data, float dest, float desto)
112 WriteString(string data, float dest, float desto)
113 WriteEntity(entity data, float dest, float desto)
115 Client & Menu : draw functions & video functions
116 ===================================================
118 float iscachedpic(string pic)
119 string precache_pic(string pic)
121 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
122 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
123 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
124 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
125 drawsetcliparea(float x, float y, float width, float height)
127 vector getimagesize(string pic)
129 float cin_open(string file, string name)
130 void cin_close(string name)
131 void cin_setstate(string name, float type)
132 float cin_getstate(string name)
133 void cin_restart(string name)
135 ==============================================================================
139 setkeydest(float dest)
141 setmousetarget(float target)
142 float getmousetarget(void)
144 callfunction(...,string function_name)
145 writetofile(float fhandle, entity ent)
146 float isfunction(string function_name)
147 vector getresolution(float number)
148 string keynumtostring(float keynum)
149 string findkeysforcommand(string command)
150 float gethostcachevalue(float type)
151 string gethostcachestring(float type, float hostnr)
153 parseentitydata(entity ent, string data)
156 #include "quakedef.h"
157 #include "progdefs.h"
159 #include "clprogdefs.h"
160 #include "mprogdefs.h"
162 #include "cl_video.h"
164 //============================================================================
165 // nice helper macros
167 #ifndef VM_NOPARMCHECK
168 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
170 #define VM_SAFEPARMCOUNT(p,f)
173 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
175 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
177 #define e10 0,0,0,0,0,0,0,0,0,0
178 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
179 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
181 //============================================================================
184 // string zone mempool
185 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
187 // temp string handling
188 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
189 #define VM_STRINGTEMP_BUFFERS 16
190 #define VM_STRINGTEMP_LENGTH 4096
191 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
192 static int vm_string_tempindex = 0;
195 #define MAX_VMFILES 256
196 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
197 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
199 qfile_t *vm_files[MAX_PRVMFILES];
201 // qc fs search handling
202 #define MAX_VMSEARCHES 128
203 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
204 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
206 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
208 static char *VM_GetTempString(void)
211 s = vm_string_temp[vm_string_tempindex];
212 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
216 void VM_CheckEmptyString (char *s)
219 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
222 //============================================================================
225 void VM_VarString(int first, char *out, int outlength)
231 outend = out + outlength - 1;
232 for (i = first;i < prog->argc && out < outend;i++)
234 s = PRVM_G_STRING((OFS_PARM0+i*3));
235 while (out < outend && *s)
245 returns true if the extension is supported by the server
247 checkextension(extensionname)
251 // kind of helper function
252 static qboolean checkextension(char *name)
258 for (e = prog->extensionstring;*e;e++)
265 while (*e && *e != ' ')
267 if (e - start == len)
268 if (!strncasecmp(start, name, len))
276 void VM_checkextension (void)
278 VM_SAFEPARMCOUNT(1,VM_checkextension);
280 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
287 This is a TERMINAL error, which will kill off the entire prog.
296 char string[VM_STRINGTEMP_LENGTH];
298 VM_VarString(0, string, sizeof(string));
299 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
302 ed = PRVM_G_EDICT(prog->self->ofs);
306 PRVM_ERROR ("%s: Program error", PRVM_NAME);
313 Dumps out self, then an error message. The program is aborted and self is
314 removed, but the level can continue.
319 void VM_objerror (void)
322 char string[VM_STRINGTEMP_LENGTH];
324 VM_VarString(0, string, sizeof(string));
325 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
328 ed = PRVM_G_EDICT (prog->self->ofs);
334 // objerror has to display the object fields -> else call
335 PRVM_ERROR ("VM_objecterror: self not defined !\n");
340 VM_print (actually used only by client and menu)
349 char string[VM_STRINGTEMP_LENGTH];
351 VM_VarString(0, string, sizeof(string));
359 broadcast print to everyone on server
364 void VM_bprint (void)
366 char string[VM_STRINGTEMP_LENGTH];
370 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
374 VM_VarString(0, string, sizeof(string));
375 SV_BroadcastPrint(string);
380 VM_sprint (menu & client but only if server.active == true)
382 single print to a specific client
384 sprint(float clientnum,...[string])
387 void VM_sprint (void)
391 char string[VM_STRINGTEMP_LENGTH];
393 //find client for this entity
394 clientnum = PRVM_G_FLOAT(OFS_PARM0);
395 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
397 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
401 client = svs.clients + clientnum;
402 VM_VarString(1, string, sizeof(string));
403 MSG_WriteChar(&client->message,svc_print);
404 MSG_WriteString(&client->message, string);
411 single print to the screen
413 centerprint(clientent, value)
416 void VM_centerprint (void)
418 char string[VM_STRINGTEMP_LENGTH];
420 VM_VarString(0, string, sizeof(string));
421 SCR_CenterPrint(string);
428 vector normalize(vector)
431 void VM_normalize (void)
437 VM_SAFEPARMCOUNT(1,VM_normalize);
439 value1 = PRVM_G_VECTOR(OFS_PARM0);
441 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
445 newvalue[0] = newvalue[1] = newvalue[2] = 0;
449 newvalue[0] = value1[0] * new;
450 newvalue[1] = value1[1] * new;
451 newvalue[2] = value1[2] * new;
454 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
469 VM_SAFEPARMCOUNT(1,VM_vlen);
471 value1 = PRVM_G_VECTOR(OFS_PARM0);
473 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
476 PRVM_G_FLOAT(OFS_RETURN) = new;
483 float vectoyaw(vector)
486 void VM_vectoyaw (void)
491 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
493 value1 = PRVM_G_VECTOR(OFS_PARM0);
495 if (value1[1] == 0 && value1[0] == 0)
499 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
504 PRVM_G_FLOAT(OFS_RETURN) = yaw;
512 vector vectoangles(vector)
515 void VM_vectoangles (void)
521 VM_SAFEPARMCOUNT(1,VM_vectoangles);
523 value1 = PRVM_G_VECTOR(OFS_PARM0);
525 if (value1[1] == 0 && value1[0] == 0)
535 // LordHavoc: optimized a bit
538 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
542 else if (value1[1] > 0)
547 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
548 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
553 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
554 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
555 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
562 Returns a number from 0<= num < 1
567 void VM_random (void)
569 VM_SAFEPARMCOUNT(0,VM_random);
571 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
578 Each entity can have eight independant sound sources, like voice,
581 Channel 0 is an auto-allocate channel, the others override anything
582 already running on that entity/channel pair.
584 An attenuation of 0 will play full volume everywhere in the level.
585 Larger attenuations will drop off.
598 entity = G_EDICT(OFS_PARM0);
599 channel = G_FLOAT(OFS_PARM1);
600 sample = G_STRING(OFS_PARM2);
601 volume = G_FLOAT(OFS_PARM3) * 255;
602 attenuation = G_FLOAT(OFS_PARM4);
604 if (volume < 0 || volume > 255)
605 Host_Error ("SV_StartSound: volume = %i", volume);
607 if (attenuation < 0 || attenuation > 4)
608 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
610 if (channel < 0 || channel > 7)
611 Host_Error ("SV_StartSound: channel = %i", channel);
613 SV_StartSound (entity, channel, sample, volume, attenuation);
621 localsound(string sample)
624 void VM_localsound(void)
628 VM_SAFEPARMCOUNT(1,VM_localsound);
630 s = PRVM_G_STRING(OFS_PARM0);
632 if(!S_LocalSound (s))
634 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
635 PRVM_G_FLOAT(OFS_RETURN) = -4;
639 PRVM_G_FLOAT(OFS_RETURN) = 1;
651 PRVM_ERROR ("%s: break statement", PRVM_NAME);
654 //============================================================================
660 Sends text over to the client's execution buffer
662 [localcmd (string) or]
666 void VM_localcmd (void)
668 VM_SAFEPARMCOUNT(1,VM_localcmd);
670 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
682 VM_SAFEPARMCOUNT(1,VM_cvar);
684 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
691 const string str_cvar (string)
694 void VM_str_cvar(void)
697 const char *cvar_string;
698 VM_SAFEPARMCOUNT(1,VM_str_cvar);
700 name = PRVM_G_STRING(OFS_PARM0);
703 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
705 VM_CheckEmptyString(name);
707 out = VM_GetTempString();
709 cvar_string = Cvar_VariableString(name);
711 strcpy(out, cvar_string);
713 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
720 void cvar_set (string,string)
723 void VM_cvar_set (void)
725 VM_SAFEPARMCOUNT(2,VM_cvar_set);
727 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
737 void VM_dprint (void)
739 char string[VM_STRINGTEMP_LENGTH];
740 if (developer.integer)
742 VM_VarString(0, string, sizeof(string));
743 Con_Printf("%s: %s", PRVM_NAME, string);
760 VM_SAFEPARMCOUNT(1, VM_ftos);
762 v = PRVM_G_FLOAT(OFS_PARM0);
764 s = VM_GetTempString();
765 if ((float)((int)v) == v)
766 sprintf(s, "%i", (int)v);
769 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
784 VM_SAFEPARMCOUNT(1,VM_fabs);
786 v = PRVM_G_FLOAT(OFS_PARM0);
787 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
802 VM_SAFEPARMCOUNT(1,VM_vtos);
804 s = VM_GetTempString();
805 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]);
806 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
821 VM_SAFEPARMCOUNT(1, VM_etos);
823 s = VM_GetTempString();
824 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
825 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
832 float stof(...[string])
837 char string[VM_STRINGTEMP_LENGTH];
838 VM_VarString(0, string, sizeof(string));
839 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
843 ========================
847 ========================
851 VM_SAFEPARMCOUNT(1, VM_itof);
852 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
856 ========================
860 ========================
865 VM_SAFEPARMCOUNT(1, VM_ftoi);
867 ent = PRVM_G_FLOAT(OFS_PARM0);
868 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
869 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
871 PRVM_G_INT(OFS_RETURN) = ent;
885 prog->xfunction->builtinsprofile += 20;
886 ed = PRVM_ED_Alloc();
898 void VM_remove (void)
901 prog->xfunction->builtinsprofile += 20;
903 VM_SAFEPARMCOUNT(1, VM_remove);
905 ed = PRVM_G_EDICT(OFS_PARM0);
906 // if (ed == prog->edicts)
907 // PRVM_ERROR ("remove: tried to remove world\n");
908 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
909 // Host_Error("remove: tried to remove a client\n");
917 entity find(entity start, .string field, string match)
928 VM_SAFEPARMCOUNT(3,VM_find);
930 e = PRVM_G_EDICTNUM(OFS_PARM0);
931 f = PRVM_G_INT(OFS_PARM1);
932 s = PRVM_G_STRING(OFS_PARM2);
936 // return reserved edict 0 (could be used for whatever the prog wants)
937 VM_RETURN_EDICT(prog->edicts);
941 for (e++ ; e < prog->num_edicts ; e++)
943 prog->xfunction->builtinsprofile++;
944 ed = PRVM_EDICT_NUM(e);
947 t = PRVM_E_STRING(ed,f);
957 VM_RETURN_EDICT(prog->edicts);
964 entity findfloat(entity start, .float field, float match)
965 entity findentity(entity start, .entity field, entity match)
968 // LordHavoc: added this for searching float, int, and entity reference fields
969 void VM_findfloat (void)
976 VM_SAFEPARMCOUNT(3,VM_findfloat);
978 e = PRVM_G_EDICTNUM(OFS_PARM0);
979 f = PRVM_G_INT(OFS_PARM1);
980 s = PRVM_G_FLOAT(OFS_PARM2);
982 for (e++ ; e < prog->num_edicts ; e++)
984 prog->xfunction->builtinsprofile++;
985 ed = PRVM_EDICT_NUM(e);
988 if (PRVM_E_FLOAT(ed,f) == s)
995 VM_RETURN_EDICT(prog->edicts);
1002 entity findchain(.string field, string match)
1005 int PRVM_ED_FindFieldOffset(const char *field);
1006 // chained search for strings in entity fields
1007 // entity(.string field, string match) findchain = #402;
1008 void VM_findchain (void)
1014 prvm_edict_t *ent, *chain;
1016 VM_SAFEPARMCOUNT(2,VM_findchain);
1018 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1019 if(!prog->flag & PRVM_FE_CHAIN)
1020 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1022 chain_of = PRVM_ED_FindFieldOffset ("chain");
1024 chain = prog->edicts;
1026 f = PRVM_G_INT(OFS_PARM0);
1027 s = PRVM_G_STRING(OFS_PARM1);
1030 VM_RETURN_EDICT(prog->edicts);
1034 ent = PRVM_NEXT_EDICT(prog->edicts);
1035 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1037 prog->xfunction->builtinsprofile++;
1040 t = PRVM_E_STRING(ent,f);
1046 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1050 VM_RETURN_EDICT(chain);
1057 entity findchainfloat(.string field, float match)
1058 entity findchainentity(.string field, entity match)
1061 // LordHavoc: chained search for float, int, and entity reference fields
1062 // entity(.string field, float match) findchainfloat = #403;
1063 void VM_findchainfloat (void)
1069 prvm_edict_t *ent, *chain;
1071 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1073 if(!prog->flag & PRVM_FE_CHAIN)
1074 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1076 chain_of = PRVM_ED_FindFieldOffset ("chain");
1078 chain = (prvm_edict_t *)prog->edicts;
1080 f = PRVM_G_INT(OFS_PARM0);
1081 s = PRVM_G_FLOAT(OFS_PARM1);
1083 ent = PRVM_NEXT_EDICT(prog->edicts);
1084 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1086 prog->xfunction->builtinsprofile++;
1089 if (PRVM_E_FLOAT(ent,f) != s)
1092 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1096 VM_RETURN_EDICT(chain);
1103 string precache_file(string)
1106 void VM_precache_file (void)
1107 { // precache_file is only used to copy files with qcc, it does nothing
1108 VM_SAFEPARMCOUNT(1,VM_precache_file);
1110 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1117 used instead of the other VM_precache_* functions in the builtin list
1121 void VM_precache_error (void)
1123 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1130 string precache_sound (string sample)
1133 void VM_precache_sound (void)
1137 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1139 s = PRVM_G_STRING(OFS_PARM0);
1140 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1141 VM_CheckEmptyString (s);
1143 if(!S_PrecacheSound (s,true, true))
1144 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1154 void VM_coredump (void)
1156 VM_SAFEPARMCOUNT(0,VM_coredump);
1158 Cbuf_AddText("prvm_edicts ");
1159 Cbuf_AddText(PRVM_NAME);
1170 void PRVM_StackTrace(void);
1171 void VM_stackdump (void)
1173 VM_SAFEPARMCOUNT(0, VM_stackdump);
1188 VM_SAFEPARMCOUNT(0, VM_crash);
1190 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1200 void VM_traceon (void)
1202 VM_SAFEPARMCOUNT(0,VM_traceon);
1214 void VM_traceoff (void)
1216 VM_SAFEPARMCOUNT(0,VM_traceoff);
1218 prog->trace = false;
1228 void VM_eprint (void)
1230 VM_SAFEPARMCOUNT(1,VM_eprint);
1232 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1246 VM_SAFEPARMCOUNT(1,VM_rint);
1248 f = PRVM_G_FLOAT(OFS_PARM0);
1250 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1252 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1262 void VM_floor (void)
1264 VM_SAFEPARMCOUNT(1,VM_floor);
1266 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1278 VM_SAFEPARMCOUNT(1,VM_ceil);
1280 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1288 entity nextent(entity)
1291 void VM_nextent (void)
1296 i = PRVM_G_EDICTNUM(OFS_PARM0);
1299 prog->xfunction->builtinsprofile++;
1301 if (i == prog->num_edicts)
1303 VM_RETURN_EDICT(prog->edicts);
1306 ent = PRVM_EDICT_NUM(i);
1307 if (!ent->p.e->free)
1309 VM_RETURN_EDICT(ent);
1316 ===============================================================================
1319 used only for client and menu
1320 severs uses VM_SV_...
1322 Write*(* data, float type, float to)
1324 ===============================================================================
1327 #define MSG_BROADCAST 0 // unreliable to all
1328 #define MSG_ONE 1 // reliable to one (msg_entity)
1329 #define MSG_ALL 2 // reliable to all
1330 #define MSG_INIT 3 // write to the init string
1332 sizebuf_t *VM_WriteDest (void)
1338 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1340 dest = G_FLOAT(OFS_PARM1);
1344 return &sv.datagram;
1347 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1348 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1349 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1351 return &svs.clients[destclient].message;
1354 return &sv.reliable_datagram;
1360 PRVM_ERROR ("WriteDest: bad destination");
1367 void VM_WriteByte (void)
1369 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1372 void VM_WriteChar (void)
1374 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1377 void VM_WriteShort (void)
1379 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1382 void VM_WriteLong (void)
1384 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1387 void VM_WriteAngle (void)
1389 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1392 void VM_WriteCoord (void)
1394 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1397 void VM_WriteString (void)
1399 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1402 void VM_WriteEntity (void)
1404 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1407 //=============================================================================
1414 changelevel(string map)
1417 void VM_changelevel (void)
1421 VM_SAFEPARMCOUNT(1, VM_changelevel);
1425 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1429 // make sure we don't issue two changelevels
1430 if (svs.changelevel_issued)
1432 svs.changelevel_issued = true;
1434 s = G_STRING(OFS_PARM0);
1435 Cbuf_AddText (va("changelevel %s\n",s));
1447 VM_SAFEPARMCOUNT(1,VM_sin);
1448 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1459 VM_SAFEPARMCOUNT(1,VM_cos);
1460 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1472 VM_SAFEPARMCOUNT(1,VM_sqrt);
1473 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1480 Returns a vector of length < 1 and > 0
1485 void VM_randomvec (void)
1490 VM_SAFEPARMCOUNT(0, VM_randomvec);
1495 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1496 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1497 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1499 while (DotProduct(temp, temp) >= 1);
1500 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1503 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1504 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1505 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1506 // length returned always > 0
1507 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1508 VectorScale(temp,length, temp);*/
1509 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1512 //=============================================================================
1518 float registercvar (string name, string value, float flags)
1521 void VM_registercvar (void)
1526 VM_SAFEPARMCOUNT(3,VM_registercvar);
1528 name = PRVM_G_STRING(OFS_PARM0);
1529 value = PRVM_G_STRING(OFS_PARM1);
1530 flags = PRVM_G_FLOAT(OFS_PARM2);
1531 PRVM_G_FLOAT(OFS_RETURN) = 0;
1533 if(flags > CVAR_MAXFLAGSVAL)
1536 // first check to see if it has already been defined
1537 if (Cvar_FindVar (name))
1540 // check for overlap with a command
1541 if (Cmd_Exists (name))
1543 Con_Printf("VM_registercvar: %s is a command\n", name);
1547 Cvar_Get(name, value, flags);
1549 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1556 returns the minimum of two supplied floats
1558 float min(float a, float b, ...[float])
1563 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1564 if (prog->argc == 2)
1565 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1566 else if (prog->argc >= 3)
1569 float f = PRVM_G_FLOAT(OFS_PARM0);
1570 for (i = 1;i < prog->argc;i++)
1571 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1572 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1573 PRVM_G_FLOAT(OFS_RETURN) = f;
1576 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1583 returns the maximum of two supplied floats
1585 float max(float a, float b, ...[float])
1590 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1591 if (prog->argc == 2)
1592 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1593 else if (prog->argc >= 3)
1596 float f = PRVM_G_FLOAT(OFS_PARM0);
1597 for (i = 1;i < prog->argc;i++)
1598 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1599 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1600 PRVM_G_FLOAT(OFS_RETURN) = f;
1603 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1610 returns number bounded by supplied range
1612 float bound(float min, float value, float max)
1615 void VM_bound (void)
1617 VM_SAFEPARMCOUNT(3,VM_bound);
1618 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1625 returns a raised to power b
1627 float pow(float a, float b)
1632 VM_SAFEPARMCOUNT(2,VM_pow);
1633 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1640 copies data from one entity to another
1642 copyentity(entity src, entity dst)
1645 void VM_copyentity (void)
1647 prvm_edict_t *in, *out;
1648 VM_SAFEPARMCOUNT(2,VM_copyentity);
1649 in = PRVM_G_EDICT(OFS_PARM0);
1650 out = PRVM_G_EDICT(OFS_PARM1);
1651 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1658 sets the color of a client and broadcasts the update to all connected clients
1660 setcolor(clientent, value)
1663 /*void PF_setcolor (void)
1669 entnum = G_EDICTNUM(OFS_PARM0);
1670 i = G_FLOAT(OFS_PARM1);
1672 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1674 Con_Print("tried to setcolor a non-client\n");
1678 client = svs.clients + entnum-1;
1679 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1682 client->old_colors = i;
1683 client->edict->v->team = (i & 15) + 1;
1685 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1686 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1687 MSG_WriteByte (&sv.reliable_datagram, i);
1690 void VM_Files_Init(void)
1692 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1695 void VM_Files_CloseAll(void)
1698 for (i = 0;i < MAX_VMFILES;i++)
1701 FS_Close(VM_FILES[i]);
1702 //VM_FILES[i] = NULL;
1704 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1711 float fopen(string filename, float mode)
1714 // float(string filename, float mode) fopen = #110;
1715 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1716 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1720 char *modestring, *filename;
1722 VM_SAFEPARMCOUNT(2,VM_fopen);
1724 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1725 if (VM_FILES[filenum] == NULL)
1727 if (filenum >= MAX_VMFILES)
1729 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1730 PRVM_G_FLOAT(OFS_RETURN) = -2;
1733 mode = PRVM_G_FLOAT(OFS_PARM1);
1736 case 0: // FILE_READ
1739 case 1: // FILE_APPEND
1742 case 2: // FILE_WRITE
1746 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1747 PRVM_G_FLOAT(OFS_RETURN) = -3;
1750 filename = PRVM_G_STRING(OFS_PARM0);
1751 // .. is parent directory on many platforms
1752 // / is parent directory on Amiga
1753 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1754 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1755 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1757 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1758 PRVM_G_FLOAT(OFS_RETURN) = -4;
1761 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1762 if (VM_FILES[filenum] == NULL && mode == 0)
1763 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1765 if (VM_FILES[filenum] == NULL)
1766 PRVM_G_FLOAT(OFS_RETURN) = -1;
1768 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1775 fclose(float fhandle)
1778 //void(float fhandle) fclose = #111; // closes a file
1779 void VM_fclose(void)
1783 VM_SAFEPARMCOUNT(1,VM_fclose);
1785 filenum = PRVM_G_FLOAT(OFS_PARM0);
1786 if (filenum < 0 || filenum >= MAX_VMFILES)
1788 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1791 if (VM_FILES[filenum] == NULL)
1793 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1796 FS_Close(VM_FILES[filenum]);
1797 VM_FILES[filenum] = NULL;
1804 string fgets(float fhandle)
1807 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1811 static char string[VM_STRINGTEMP_LENGTH];
1814 VM_SAFEPARMCOUNT(1,VM_fgets);
1816 filenum = PRVM_G_FLOAT(OFS_PARM0);
1817 if (filenum < 0 || filenum >= MAX_VMFILES)
1819 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1822 if (VM_FILES[filenum] == NULL)
1824 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1830 c = FS_Getc(VM_FILES[filenum]);
1831 if (c == '\r' || c == '\n' || c < 0)
1833 if (end < VM_STRINGTEMP_LENGTH - 1)
1837 // remove \n following \r
1839 c = FS_Getc(VM_FILES[filenum]);
1840 if (developer.integer)
1841 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1843 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1845 PRVM_G_INT(OFS_RETURN) = 0;
1852 fputs(float fhandle, string s)
1855 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1859 char string[VM_STRINGTEMP_LENGTH];
1862 VM_SAFEPARMCOUNT(2,VM_fputs);
1864 filenum = PRVM_G_FLOAT(OFS_PARM0);
1865 if (filenum < 0 || filenum >= MAX_VMFILES)
1867 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1870 if (VM_FILES[filenum] == NULL)
1872 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1875 VM_VarString(1, string, sizeof(string));
1876 if ((stringlength = strlen(string)))
1877 FS_Write(VM_FILES[filenum], string, stringlength);
1878 if (developer.integer)
1879 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1886 float strlen(string s)
1889 //float(string s) strlen = #114; // returns how many characters are in a string
1890 void VM_strlen(void)
1894 VM_SAFEPARMCOUNT(1,VM_strlen);
1896 s = PRVM_G_STRING(OFS_PARM0);
1898 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1900 PRVM_G_FLOAT(OFS_RETURN) = 0;
1907 string strcat(string,string,...[string])
1910 //string(string s1, string s2) strcat = #115;
1911 // concatenates two strings (for example "abc", "def" would return "abcdef")
1912 // and returns as a tempstring
1913 void VM_strcat(void)
1918 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1920 s = VM_GetTempString();
1921 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1922 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1929 string substring(string s, float start, float length)
1932 // string(string s, float start, float length) substring = #116;
1933 // returns a section of a string as a tempstring
1934 void VM_substring(void)
1936 int i, start, length;
1939 VM_SAFEPARMCOUNT(3,VM_substring);
1941 string = VM_GetTempString();
1942 s = PRVM_G_STRING(OFS_PARM0);
1943 start = PRVM_G_FLOAT(OFS_PARM1);
1944 length = PRVM_G_FLOAT(OFS_PARM2);
1947 for (i = 0;i < start && *s;i++, s++);
1948 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1951 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1958 vector stov(string s)
1961 //vector(string s) stov = #117; // returns vector value from a string
1964 char string[VM_STRINGTEMP_LENGTH];
1966 VM_SAFEPARMCOUNT(1,VM_stov);
1968 VM_VarString(0, string, sizeof(string));
1969 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1976 string strzone(string s)
1979 //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)
1980 void VM_strzone(void)
1984 VM_SAFEPARMCOUNT(1,VM_strzone);
1986 in = PRVM_G_STRING(OFS_PARM0);
1987 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1989 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1999 //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!!!)
2000 void VM_strunzone(void)
2003 VM_SAFEPARMCOUNT(1,VM_strunzone);
2005 str = PRVM_G_STRING(OFS_PARM0);
2006 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2007 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2014 VM_command (used by client and menu)
2016 clientcommand(float client, string s) (for client and menu)
2019 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2020 //this function originally written by KrimZon, made shorter by LordHavoc
2021 void VM_clcommand (void)
2023 client_t *temp_client;
2026 VM_SAFEPARMCOUNT(2,VM_clcommand);
2028 i = PRVM_G_FLOAT(OFS_PARM0);
2029 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2031 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2035 temp_client = host_client;
2036 host_client = svs.clients + i;
2037 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2038 host_client = temp_client;
2046 float tokenize(string s)
2049 //float(string s) tokenize = #441;
2050 // takes apart a string into individal words (access them with argv), returns how many
2051 // this function originally written by KrimZon, made shorter by LordHavoc
2052 static char **tokens = NULL;
2053 static int max_tokens, num_tokens = 0;
2054 void VM_tokenize (void)
2059 VM_SAFEPARMCOUNT(1,VM_tokenize);
2061 str = PRVM_G_STRING(OFS_PARM0);
2066 for (i=0;i<num_tokens;i++)
2072 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2073 max_tokens = strlen(str);
2075 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2077 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2078 strcpy(tokens[num_tokens], com_token);
2081 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2088 string argv(float n)
2091 //string(float n) argv = #442;
2092 // returns a word from the tokenized string (returns nothing for an invalid index)
2093 // this function originally written by KrimZon, made shorter by LordHavoc
2098 VM_SAFEPARMCOUNT(1,VM_argv);
2100 token_num = PRVM_G_FLOAT(OFS_PARM0);
2101 if (token_num >= 0 && token_num < num_tokens)
2102 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2104 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2108 //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)
2109 void PF_setattachment (void)
2111 edict_t *e = G_EDICT(OFS_PARM0);
2112 edict_t *tagentity = G_EDICT(OFS_PARM1);
2113 char *tagname = G_STRING(OFS_PARM2);
2118 if (tagentity == NULL)
2119 tagentity = sv.edicts;
2121 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2123 v->edict = EDICT_TO_PROG(tagentity);
2125 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2128 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2130 modelindex = (int)tagentity->v->modelindex;
2131 if (modelindex >= 0 && modelindex < MAX_MODELS)
2133 model = sv.models[modelindex];
2134 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2135 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2136 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2138 // FIXME: use a model function to get tag info (need to handle skeletal)
2139 if (v->_float == 0 && model->alias.aliasnum_tags)
2140 for (i = 0;i < model->alias.aliasnum_tags;i++)
2141 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2144 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);
2147 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));
2158 void VM_isserver(void)
2160 VM_SAFEPARMCOUNT(0,VM_serverstate);
2162 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2172 void VM_clientcount(void)
2174 VM_SAFEPARMCOUNT(0,VM_clientcount);
2176 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2186 void VM_clientstate(void)
2188 VM_SAFEPARMCOUNT(0,VM_clientstate);
2190 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2197 float getostype(void)
2199 */ // not used at the moment -> not included in the common list
2200 void VM_getostype(void)
2202 VM_SAFEPARMCOUNT(0,VM_getostype);
2207 OS_MAC - not supported
2211 PRVM_G_FLOAT(OFS_RETURN) = 0;
2213 PRVM_G_FLOAT(OFS_RETURN) = 2;
2215 PRVM_G_FLOAT(OFS_RETURN) = 1;
2223 vector getmousepos()
2226 void VM_getmousepos(void)
2229 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2231 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2232 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2233 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2243 void VM_gettime(void)
2245 VM_SAFEPARMCOUNT(0,VM_gettime);
2247 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2254 loadfromdata(string data)
2257 void VM_loadfromdata(void)
2259 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2261 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2265 ========================
2266 VM_M_parseentitydata
2268 parseentitydata(entity ent, string data)
2269 ========================
2271 void VM_M_parseentitydata(void)
2276 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2278 // get edict and test it
2279 ent = PRVM_G_EDICT(OFS_PARM0);
2281 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2283 data = PRVM_G_STRING(OFS_PARM1);
2285 // parse the opening brace
2286 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2287 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2289 PRVM_ED_ParseEdict (data, ent);
2296 loadfromfile(string file)
2299 void VM_loadfromfile(void)
2304 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2306 filename = PRVM_G_STRING(OFS_PARM0);
2307 // .. is parent directory on many platforms
2308 // / is parent directory on Amiga
2309 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2310 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2311 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2313 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2314 PRVM_G_FLOAT(OFS_RETURN) = -4;
2318 // not conform with VM_fopen
2319 data = FS_LoadFile(filename, tempmempool, false);
2321 PRVM_G_FLOAT(OFS_RETURN) = -1;
2323 PRVM_ED_LoadFromFile(data);
2334 float mod(float val, float m)
2337 void VM_modulo(void)
2340 VM_SAFEPARMCOUNT(2,VM_module);
2342 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2343 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2345 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2348 void VM_Search_Init(void)
2350 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2353 void VM_Search_Reset(void)
2356 // reset the fssearch list
2357 for(i = 0; i < MAX_VMSEARCHES; i++)
2358 if(VM_SEARCHLIST[i])
2359 FS_FreeSearch(VM_SEARCHLIST[i]);
2360 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2367 float search_begin(string pattern, float caseinsensitive, float quiet)
2370 void VM_search_begin(void)
2374 int caseinsens, quiet;
2376 VM_SAFEPARMCOUNT(3, VM_search_begin);
2378 pattern = PRVM_G_STRING(OFS_PARM0);
2380 VM_CheckEmptyString(pattern);
2382 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2383 quiet = PRVM_G_FLOAT(OFS_PARM2);
2385 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2386 if(!VM_SEARCHLIST[handle])
2389 if(handle >= MAX_VMSEARCHES)
2391 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2392 PRVM_G_FLOAT(OFS_RETURN) = -2;
2396 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2397 PRVM_G_FLOAT(OFS_RETURN) = -1;
2399 PRVM_G_FLOAT(OFS_RETURN) = handle;
2406 void search_end(float handle)
2409 void VM_search_end(void)
2412 VM_SAFEPARMCOUNT(1, VM_search_end);
2414 handle = PRVM_G_FLOAT(OFS_PARM0);
2416 if(handle < 0 || handle >= MAX_VMSEARCHES)
2418 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2421 if(VM_SEARCHLIST[handle] == NULL)
2423 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2427 FS_FreeSearch(VM_SEARCHLIST[handle]);
2428 VM_SEARCHLIST[handle] = NULL;
2435 float search_getsize(float handle)
2438 void VM_search_getsize(void)
2441 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2443 handle = PRVM_G_FLOAT(OFS_PARM0);
2445 if(handle < 0 || handle >= MAX_VMSEARCHES)
2447 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2450 if(VM_SEARCHLIST[handle] == NULL)
2452 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2456 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2461 VM_search_getfilename
2463 string search_getfilename(float handle, float num)
2466 void VM_search_getfilename(void)
2468 int handle, filenum;
2470 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2472 handle = PRVM_G_FLOAT(OFS_PARM0);
2473 filenum = PRVM_G_FLOAT(OFS_PARM1);
2475 if(handle < 0 || handle >= MAX_VMSEARCHES)
2477 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2480 if(VM_SEARCHLIST[handle] == NULL)
2482 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2485 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2487 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2491 tmp = VM_GetTempString();
2492 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2494 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2501 string chr(float ascii)
2507 VM_SAFEPARMCOUNT(1, VM_chr);
2509 tmp = VM_GetTempString();
2510 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2513 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2516 //=============================================================================
2517 // Draw builtins (client & menu)
2523 float iscachedpic(string pic)
2526 void VM_iscachedpic(void)
2528 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2530 // drawq hasnt such a function, thus always return true
2531 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2538 string precache_pic(string pic)
2541 void VM_precache_pic(void)
2545 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2547 s = PRVM_G_STRING(OFS_PARM0);
2548 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2551 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2553 VM_CheckEmptyString (s);
2555 if(!Draw_CachePic(s))
2556 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2566 void VM_freepic(void)
2570 VM_SAFEPARMCOUNT(1,VM_freepic);
2572 s = PRVM_G_STRING(OFS_PARM0);
2575 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2577 VM_CheckEmptyString (s);
2586 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2589 void VM_drawcharacter(void)
2591 float *pos,*scale,*rgb;
2594 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2596 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2599 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2600 PRVM_G_FLOAT(OFS_RETURN) = -1;
2604 pos = PRVM_G_VECTOR(OFS_PARM0);
2605 scale = PRVM_G_VECTOR(OFS_PARM2);
2606 rgb = PRVM_G_VECTOR(OFS_PARM3);
2607 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2609 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2611 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2612 PRVM_G_FLOAT(OFS_RETURN) = -2;
2616 if(pos[2] || scale[2])
2617 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")));
2619 if(!scale[0] || !scale[1])
2621 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2622 PRVM_G_FLOAT(OFS_RETURN) = -3;
2626 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2627 PRVM_G_FLOAT(OFS_RETURN) = 1;
2634 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2637 void VM_drawstring(void)
2639 float *pos,*scale,*rgb;
2642 VM_SAFEPARMCOUNT(6,VM_drawstring);
2644 string = PRVM_G_STRING(OFS_PARM1);
2647 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2648 PRVM_G_FLOAT(OFS_RETURN) = -1;
2652 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to the precolored letters, too?
2654 pos = PRVM_G_VECTOR(OFS_PARM0);
2655 scale = PRVM_G_VECTOR(OFS_PARM2);
2656 rgb = PRVM_G_VECTOR(OFS_PARM3);
2657 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2659 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2661 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2662 PRVM_G_FLOAT(OFS_RETURN) = -2;
2666 if(!scale[0] || !scale[1])
2668 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2669 PRVM_G_FLOAT(OFS_RETURN) = -3;
2673 if(pos[2] || scale[2])
2674 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")));
2676 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2677 PRVM_G_FLOAT(OFS_RETURN) = 1;
2683 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2686 void VM_drawpic(void)
2689 float *size, *pos, *rgb;
2692 VM_SAFEPARMCOUNT(6,VM_drawpic);
2694 pic = PRVM_G_STRING(OFS_PARM1);
2698 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2699 PRVM_G_FLOAT(OFS_RETURN) = -1;
2703 VM_CheckEmptyString (pic);
2705 // is pic cached ? no function yet for that
2708 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2709 PRVM_G_FLOAT(OFS_RETURN) = -4;
2713 pos = PRVM_G_VECTOR(OFS_PARM0);
2714 size = PRVM_G_VECTOR(OFS_PARM2);
2715 rgb = PRVM_G_VECTOR(OFS_PARM3);
2716 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2718 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2720 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2721 PRVM_G_FLOAT(OFS_RETURN) = -2;
2725 if(pos[2] || size[2])
2726 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")));
2728 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2729 PRVM_G_FLOAT(OFS_RETURN) = 1;
2736 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2739 void VM_drawfill(void)
2741 float *size, *pos, *rgb;
2744 VM_SAFEPARMCOUNT(5,VM_drawfill);
2747 pos = PRVM_G_VECTOR(OFS_PARM0);
2748 size = PRVM_G_VECTOR(OFS_PARM1);
2749 rgb = PRVM_G_VECTOR(OFS_PARM2);
2750 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2752 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2754 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2755 PRVM_G_FLOAT(OFS_RETURN) = -2;
2759 if(pos[2] || size[2])
2760 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")));
2762 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2763 PRVM_G_FLOAT(OFS_RETURN) = 1;
2770 drawsetcliparea(float x, float y, float width, float height)
2773 void VM_drawsetcliparea(void)
2776 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2778 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2779 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2780 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2781 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2783 DrawQ_SetClipArea(x,y,w,h);
2788 VM_drawresetcliparea
2793 void VM_drawresetcliparea(void)
2795 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2797 DrawQ_ResetClipArea();
2804 vector getimagesize(string pic)
2807 void VM_getimagesize(void)
2812 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2814 p = PRVM_G_STRING(OFS_PARM0);
2817 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2819 VM_CheckEmptyString (p);
2821 pic = Draw_CachePic (p);
2823 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2824 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2825 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2828 // CL_Video interface functions
2831 ========================
2834 float cin_open(string file, string name)
2835 ========================
2837 void VM_cin_open( void )
2842 file = PRVM_G_STRING( OFS_PARM0 );
2843 name = PRVM_G_STRING( OFS_PARM1 );
2845 VM_CheckEmptyString( file );
2846 VM_CheckEmptyString( name );
2848 if( CL_OpenVideo( file, name, MENUOWNER ) )
2849 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2851 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2855 ========================
2858 void cin_close(string name)
2859 ========================
2861 void VM_cin_close( void )
2865 name = PRVM_G_STRING( OFS_PARM0 );
2866 VM_CheckEmptyString( name );
2868 CL_CloseVideo( CL_GetVideo( name ) );
2872 ========================
2874 void cin_setstate(string name, float type)
2875 ========================
2877 void VM_cin_setstate( void )
2880 clvideostate_t state;
2883 name = PRVM_G_STRING( OFS_PARM0 );
2884 VM_CheckEmptyString( name );
2886 state = PRVM_G_FLOAT( OFS_PARM1 );
2888 video = CL_GetVideo( name );
2889 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2890 CL_SetVideoState( video, state );
2894 ========================
2897 float cin_getstate(string name)
2898 ========================
2900 void VM_cin_getstate( void )
2905 name = PRVM_G_STRING( OFS_PARM0 );
2906 VM_CheckEmptyString( name );
2908 video = CL_GetVideo( name );
2910 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2912 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2916 ========================
2919 void cin_restart(string name)
2920 ========================
2922 void VM_cin_restart( void )
2927 name = PRVM_G_STRING( OFS_PARM0 );
2928 VM_CheckEmptyString( name );
2930 video = CL_GetVideo( name );
2932 CL_RestartVideo( video );
2935 void VM_Cmd_Init(void)
2937 // only init the stuff for the current prog
2938 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2943 void VM_Cmd_Reset(void)
2945 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2946 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
2947 memheader_t *header;
2950 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
2951 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
2954 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2955 CL_PurgeOwner( MENUOWNER );
2957 VM_Files_CloseAll();
2960 //============================================================================
2963 char *vm_sv_extensions =
2966 prvm_builtin_t vm_sv_builtins[] = {
2967 0 // to be consistent with the old vm
2970 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2972 void VM_SV_Cmd_Init(void)
2976 void VM_SV_Cmd_Reset(void)
2980 //============================================================================
2983 char *vm_cl_extensions =
2986 prvm_builtin_t vm_cl_builtins[] = {
2987 0 // to be consistent with the old vm
2990 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2992 void VM_CL_Cmd_Init(void)
2996 void VM_CL_Cmd_Reset(void)
3000 //============================================================================
3003 char *vm_m_extensions =
3010 setmousetarget(float target)
3013 void VM_M_setmousetarget(void)
3015 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3017 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3020 in_client_mouse = false;
3023 in_client_mouse = true;
3026 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3034 float getmousetarget
3037 void VM_M_getmousetarget(void)
3039 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3042 PRVM_G_FLOAT(OFS_RETURN) = 2;
3044 PRVM_G_FLOAT(OFS_RETURN) = 1;
3053 setkeydest(float dest)
3056 void VM_M_setkeydest(void)
3058 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3060 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3064 key_dest = key_game;
3068 key_dest = key_menu;
3072 // key_dest = key_message
3075 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3086 void VM_M_getkeydest(void)
3088 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3090 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3094 PRVM_G_FLOAT(OFS_RETURN) = 0;
3097 PRVM_G_FLOAT(OFS_RETURN) = 2;
3101 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3104 PRVM_G_FLOAT(OFS_RETURN) = 3;
3112 callfunction(...,string function_name)
3116 mfunction_t *PRVM_ED_FindFunction (const char *name);
3117 void VM_M_callfunction(void)
3123 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3125 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3128 PRVM_ERROR("VM_M_callfunction: null string !\n");
3130 VM_CheckEmptyString(s);
3132 func = PRVM_ED_FindFunction(s);
3135 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3136 else if (func->first_statement < 0)
3138 // negative statements are built in functions
3139 int builtinnumber = -func->first_statement;
3140 prog->xfunction->builtinsprofile++;
3141 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3142 prog->builtins[builtinnumber]();
3144 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3149 PRVM_ExecuteProgram(func - prog->functions,"");
3158 float isfunction(string function_name)
3161 mfunction_t *PRVM_ED_FindFunction (const char *name);
3162 void VM_M_isfunction(void)
3167 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3169 s = PRVM_G_STRING(OFS_PARM0);
3172 PRVM_ERROR("VM_M_isfunction: null string !\n");
3174 VM_CheckEmptyString(s);
3176 func = PRVM_ED_FindFunction(s);
3179 PRVM_G_FLOAT(OFS_RETURN) = false;
3181 PRVM_G_FLOAT(OFS_RETURN) = true;
3188 writetofile(float fhandle, entity ent)
3191 void VM_M_writetofile(void)
3196 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3198 filenum = PRVM_G_FLOAT(OFS_PARM0);
3199 if (filenum < 0 || filenum >= MAX_VMFILES)
3201 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3204 if (VM_FILES[filenum] == NULL)
3206 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3210 ent = PRVM_G_EDICT(OFS_PARM1);
3213 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3217 PRVM_ED_Write (VM_FILES[filenum], ent);
3224 vector getresolution(float number)
3227 extern unsigned short video_resolutions[][2];
3228 void VM_M_getresolution(void)
3231 VM_SAFEPARMCOUNT(1, VM_getresolution);
3233 nr = PRVM_G_FLOAT(OFS_PARM0);
3236 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3237 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3238 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3245 string keynumtostring(float keynum)
3248 void VM_M_keynumtostring(void)
3252 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3254 keynum = PRVM_G_FLOAT(OFS_PARM0);
3256 tmp = VM_GetTempString();
3258 strcpy(tmp, Key_KeynumToString(keynum));
3260 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3265 VM_M_findkeysforcommand
3267 string findkeysforcommand(string command)
3269 the returned string is an altstring
3272 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3274 void M_FindKeysForCommand(char *command, int *keys);
3275 void VM_M_findkeysforcommand(void)
3281 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3283 cmd = PRVM_G_STRING(OFS_PARM0);
3285 VM_CheckEmptyString(cmd);
3287 (ret = VM_GetTempString())[0] = 0;
3289 M_FindKeysForCommand(cmd, keys);
3291 for(i = 0; i < NUMKEYS; i++)
3292 ret = strcat(ret, va(" \'%i\'", keys[i]));
3294 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3299 VM_M_gethostcachecount
3301 float gethostcachevalue(float type)
3312 void VM_M_gethostcachevalue( void )
3315 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3317 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3319 type = PRVM_G_FLOAT( OFS_PARM0 );
3320 if( type < 0 || type > 4 )
3321 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3325 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3328 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3331 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3334 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3337 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3344 VM_M_gethostcachestring
3346 string gethostcachestring(float type, float hostnr)
3354 void VM_M_gethostcachestring(void)
3359 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3361 PRVM_G_INT(OFS_RETURN) = 0;
3363 type = PRVM_G_FLOAT(OFS_PARM0);
3365 if(type < 0 || type > 2)
3367 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3371 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3373 if(hostnr < 0 || hostnr >= hostCacheCount)
3375 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3380 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3381 else if( type == 1 )
3382 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3384 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3387 prvm_builtin_t vm_m_builtins[] = {
3388 0, // to be consistent with the old vm
3389 // common builtings (mostly)
3466 VM_search_getfilename, // 77
3483 VM_WriteEntity, // 408
3499 VM_drawresetcliparea,
3500 VM_getimagesize,// 460
3505 VM_cin_restart, // 465
3514 VM_M_setmousetarget,
3515 VM_M_getmousetarget,
3520 VM_M_keynumtostring,
3521 VM_M_findkeysforcommand,// 610
3522 VM_M_gethostcachevalue,
3523 VM_M_gethostcachestring,
3524 VM_M_parseentitydata // 613
3527 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3529 void VM_M_Cmd_Init(void)
3534 void VM_M_Cmd_Reset(void)