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
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)
130 ==============================================================================
134 setkeydest(float dest)
136 setmousetarget(float target)
137 float getmousetarget(void)
139 callfunction(...,string function_name)
140 writetofile(float fhandle, entity ent)
141 float isfunction(string function_name)
142 vector getresolution(float number)
143 string keynumtostring(float keynum)
144 string findkeysforcommand(string command)
145 float gethostcachevalue(float type)
146 string gethostcachestring(float type, float hostnr)
148 parseentitydata(entity ent, string data)
151 #include "quakedef.h"
152 #include "progdefs.h"
154 #include "clprogdefs.h"
155 #include "mprogdefs.h"
157 //============================================================================
158 // nice helper macros
160 #ifndef VM_NOPARMCHECK
161 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
163 #define VM_SAFEPARMCOUNT(p,f)
166 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
168 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
170 #define e10 0,0,0,0,0,0,0,0,0,0
171 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
172 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
174 //============================================================================
177 // string zone mempool
178 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
180 // temp string handling
181 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
182 #define VM_STRINGTEMP_BUFFERS 16
183 #define VM_STRINGTEMP_LENGTH 4096
184 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
185 static int vm_string_tempindex = 0;
188 #define MAX_VMFILES 256
189 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
190 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
192 qfile_t *vm_files[MAX_PRVMFILES];
194 // qc fs search handling
195 #define MAX_VMSEARCHES 128
196 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
197 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
199 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
201 static char *VM_GetTempString(void)
204 s = vm_string_temp[vm_string_tempindex];
205 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
209 void VM_CheckEmptyString (char *s)
212 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
215 //============================================================================
218 void VM_VarString(int first, char *out, int outlength)
224 outend = out + outlength - 1;
225 for (i = first;i < prog->argc && out < outend;i++)
227 s = PRVM_G_STRING((OFS_PARM0+i*3));
228 while (out < outend && *s)
238 returns true if the extension is supported by the server
240 checkextension(extensionname)
244 // kind of helper function
245 static qboolean checkextension(char *name)
251 for (e = prog->extensionstring;*e;e++)
258 while (*e && *e != ' ')
260 if (e - start == len)
261 if (!strncasecmp(start, name, len))
269 void VM_checkextension (void)
271 VM_SAFEPARMCOUNT(1,VM_checkextension);
273 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
280 This is a TERMINAL error, which will kill off the entire prog.
289 char string[VM_STRINGTEMP_LENGTH];
291 VM_VarString(0, string, sizeof(string));
292 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
295 ed = PRVM_G_EDICT(prog->self->ofs);
299 PRVM_ERROR ("%s: Program error", PRVM_NAME);
306 Dumps out self, then an error message. The program is aborted and self is
307 removed, but the level can continue.
312 void VM_objerror (void)
315 char string[VM_STRINGTEMP_LENGTH];
317 VM_VarString(0, string, sizeof(string));
318 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
321 ed = PRVM_G_EDICT (prog->self->ofs);
327 // objerror has to display the object fields -> else call
328 PRVM_ERROR ("VM_objecterror: self not defined !\n");
333 VM_print (actually used only by client and menu)
342 char string[VM_STRINGTEMP_LENGTH];
344 VM_VarString(0, string, sizeof(string));
352 broadcast print to everyone on server
357 void VM_bprint (void)
359 char string[VM_STRINGTEMP_LENGTH];
363 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
367 VM_VarString(0, string, sizeof(string));
368 SV_BroadcastPrint(string);
373 VM_sprint (menu & client but only if server.active == true)
375 single print to a specific client
377 sprint(float clientnum,...[string])
380 void VM_sprint (void)
384 char string[VM_STRINGTEMP_LENGTH];
386 //find client for this entity
387 clientnum = PRVM_G_FLOAT(OFS_PARM0);
388 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
390 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
394 client = svs.clients + clientnum;
395 VM_VarString(1, string, sizeof(string));
396 MSG_WriteChar(&client->message,svc_print);
397 MSG_WriteString(&client->message, string);
404 single print to the screen
406 centerprint(clientent, value)
409 void VM_centerprint (void)
411 char string[VM_STRINGTEMP_LENGTH];
413 VM_VarString(0, string, sizeof(string));
414 SCR_CenterPrint(string);
421 vector normalize(vector)
424 void VM_normalize (void)
430 VM_SAFEPARMCOUNT(1,VM_normalize);
432 value1 = PRVM_G_VECTOR(OFS_PARM0);
434 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
438 newvalue[0] = newvalue[1] = newvalue[2] = 0;
442 newvalue[0] = value1[0] * new;
443 newvalue[1] = value1[1] * new;
444 newvalue[2] = value1[2] * new;
447 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
462 VM_SAFEPARMCOUNT(1,VM_vlen);
464 value1 = PRVM_G_VECTOR(OFS_PARM0);
466 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
469 PRVM_G_FLOAT(OFS_RETURN) = new;
476 float vectoyaw(vector)
479 void VM_vectoyaw (void)
484 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
486 value1 = PRVM_G_VECTOR(OFS_PARM0);
488 if (value1[1] == 0 && value1[0] == 0)
492 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
497 PRVM_G_FLOAT(OFS_RETURN) = yaw;
505 vector vectoangles(vector)
508 void VM_vectoangles (void)
514 VM_SAFEPARMCOUNT(1,VM_vectoangles);
516 value1 = PRVM_G_VECTOR(OFS_PARM0);
518 if (value1[1] == 0 && value1[0] == 0)
528 // LordHavoc: optimized a bit
531 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
535 else if (value1[1] > 0)
540 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
541 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
546 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
547 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
548 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
555 Returns a number from 0<= num < 1
560 void VM_random (void)
562 VM_SAFEPARMCOUNT(0,VM_random);
564 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
571 Each entity can have eight independant sound sources, like voice,
574 Channel 0 is an auto-allocate channel, the others override anything
575 already running on that entity/channel pair.
577 An attenuation of 0 will play full volume everywhere in the level.
578 Larger attenuations will drop off.
591 entity = G_EDICT(OFS_PARM0);
592 channel = G_FLOAT(OFS_PARM1);
593 sample = G_STRING(OFS_PARM2);
594 volume = G_FLOAT(OFS_PARM3) * 255;
595 attenuation = G_FLOAT(OFS_PARM4);
597 if (volume < 0 || volume > 255)
598 Host_Error ("SV_StartSound: volume = %i", volume);
600 if (attenuation < 0 || attenuation > 4)
601 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
603 if (channel < 0 || channel > 7)
604 Host_Error ("SV_StartSound: channel = %i", channel);
606 SV_StartSound (entity, channel, sample, volume, attenuation);
614 localsound(string sample)
617 void VM_localsound(void)
621 VM_SAFEPARMCOUNT(1,VM_localsound);
623 s = PRVM_G_STRING(OFS_PARM0);
625 if(!S_LocalSound (s))
627 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
628 PRVM_G_FLOAT(OFS_RETURN) = -4;
632 PRVM_G_FLOAT(OFS_RETURN) = 1;
644 PRVM_ERROR ("%s: break statement", PRVM_NAME);
647 //============================================================================
653 Sends text over to the client's execution buffer
655 [localcmd (string) or]
659 void VM_localcmd (void)
661 VM_SAFEPARMCOUNT(1,VM_localcmd);
663 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
675 VM_SAFEPARMCOUNT(1,VM_cvar);
677 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
684 const string str_cvar (string)
687 void VM_str_cvar(void)
690 const char *cvar_string;
691 VM_SAFEPARMCOUNT(1,VM_str_cvar);
693 name = PRVM_G_STRING(OFS_PARM0);
696 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
698 VM_CheckEmptyString(name);
700 out = VM_GetTempString();
702 cvar_string = Cvar_VariableString(name);
704 strcpy(out, cvar_string);
706 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
713 void cvar_set (string,string)
716 void VM_cvar_set (void)
718 VM_SAFEPARMCOUNT(2,VM_cvar_set);
720 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
730 void VM_dprint (void)
732 char string[VM_STRINGTEMP_LENGTH];
733 if (developer.integer)
735 VM_VarString(0, string, sizeof(string));
736 Con_Printf("%s: %s", PRVM_NAME, string);
753 VM_SAFEPARMCOUNT(1, VM_ftos);
755 v = PRVM_G_FLOAT(OFS_PARM0);
757 s = VM_GetTempString();
758 if ((float)((int)v) == v)
759 sprintf(s, "%i", (int)v);
762 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
777 VM_SAFEPARMCOUNT(1,VM_fabs);
779 v = PRVM_G_FLOAT(OFS_PARM0);
780 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
795 VM_SAFEPARMCOUNT(1,VM_vtos);
797 s = VM_GetTempString();
798 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]);
799 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
814 VM_SAFEPARMCOUNT(1, VM_etos);
816 s = VM_GetTempString();
817 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
818 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
825 float stof(...[string])
830 char string[VM_STRINGTEMP_LENGTH];
831 VM_VarString(0, string, sizeof(string));
832 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
836 ========================
840 ========================
844 VM_SAFEPARMCOUNT(1, VM_itof);
845 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
849 ========================
853 ========================
858 VM_SAFEPARMCOUNT(1, VM_ftoi);
860 ent = PRVM_G_FLOAT(OFS_PARM0);
861 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
862 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
864 PRVM_G_INT(OFS_RETURN) = ent;
878 prog->xfunction->builtinsprofile += 20;
879 ed = PRVM_ED_Alloc();
891 void VM_remove (void)
894 prog->xfunction->builtinsprofile += 20;
896 VM_SAFEPARMCOUNT(1, VM_remove);
898 ed = PRVM_G_EDICT(OFS_PARM0);
899 // if (ed == prog->edicts)
900 // PRVM_ERROR ("remove: tried to remove world\n");
901 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
902 // Host_Error("remove: tried to remove a client\n");
910 entity find(entity start, .string field, string match)
921 VM_SAFEPARMCOUNT(3,VM_find);
923 e = PRVM_G_EDICTNUM(OFS_PARM0);
924 f = PRVM_G_INT(OFS_PARM1);
925 s = PRVM_G_STRING(OFS_PARM2);
929 // return reserved edict 0 (could be used for whatever the prog wants)
930 VM_RETURN_EDICT(prog->edicts);
934 for (e++ ; e < prog->num_edicts ; e++)
936 prog->xfunction->builtinsprofile++;
937 ed = PRVM_EDICT_NUM(e);
940 t = PRVM_E_STRING(ed,f);
950 VM_RETURN_EDICT(prog->edicts);
957 entity findfloat(entity start, .float field, float match)
958 entity findentity(entity start, .entity field, entity match)
961 // LordHavoc: added this for searching float, int, and entity reference fields
962 void VM_findfloat (void)
969 VM_SAFEPARMCOUNT(3,VM_findfloat);
971 e = PRVM_G_EDICTNUM(OFS_PARM0);
972 f = PRVM_G_INT(OFS_PARM1);
973 s = PRVM_G_FLOAT(OFS_PARM2);
975 for (e++ ; e < prog->num_edicts ; e++)
977 prog->xfunction->builtinsprofile++;
978 ed = PRVM_EDICT_NUM(e);
981 if (PRVM_E_FLOAT(ed,f) == s)
988 VM_RETURN_EDICT(prog->edicts);
995 entity findchain(.string field, string match)
998 int PRVM_ED_FindFieldOffset(const char *field);
999 // chained search for strings in entity fields
1000 // entity(.string field, string match) findchain = #402;
1001 void VM_findchain (void)
1007 prvm_edict_t *ent, *chain;
1009 VM_SAFEPARMCOUNT(2,VM_findchain);
1011 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1012 if(!prog->flag & PRVM_FE_CHAIN)
1013 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1015 chain_of = PRVM_ED_FindFieldOffset ("chain");
1017 chain = prog->edicts;
1019 f = PRVM_G_INT(OFS_PARM0);
1020 s = PRVM_G_STRING(OFS_PARM1);
1023 VM_RETURN_EDICT(prog->edicts);
1027 ent = PRVM_NEXT_EDICT(prog->edicts);
1028 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1030 prog->xfunction->builtinsprofile++;
1033 t = PRVM_E_STRING(ent,f);
1039 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1043 VM_RETURN_EDICT(chain);
1050 entity findchainfloat(.string field, float match)
1051 entity findchainentity(.string field, entity match)
1054 // LordHavoc: chained search for float, int, and entity reference fields
1055 // entity(.string field, float match) findchainfloat = #403;
1056 void VM_findchainfloat (void)
1062 prvm_edict_t *ent, *chain;
1064 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1066 if(!prog->flag & PRVM_FE_CHAIN)
1067 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1069 chain_of = PRVM_ED_FindFieldOffset ("chain");
1071 chain = (prvm_edict_t *)prog->edicts;
1073 f = PRVM_G_INT(OFS_PARM0);
1074 s = PRVM_G_FLOAT(OFS_PARM1);
1076 ent = PRVM_NEXT_EDICT(prog->edicts);
1077 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1079 prog->xfunction->builtinsprofile++;
1082 if (PRVM_E_FLOAT(ent,f) != s)
1085 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1089 VM_RETURN_EDICT(chain);
1096 string precache_file(string)
1099 void VM_precache_file (void)
1100 { // precache_file is only used to copy files with qcc, it does nothing
1101 VM_SAFEPARMCOUNT(1,VM_precache_file);
1103 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1110 used instead of the other VM_precache_* functions in the builtin list
1114 void VM_precache_error (void)
1116 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1123 string precache_sound (string sample)
1126 void VM_precache_sound (void)
1130 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1132 s = PRVM_G_STRING(OFS_PARM0);
1133 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1134 VM_CheckEmptyString (s);
1136 if(!S_PrecacheSound (s,true, true))
1137 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1147 void VM_coredump (void)
1149 VM_SAFEPARMCOUNT(0,VM_coredump);
1151 Cbuf_AddText("prvm_edicts ");
1152 Cbuf_AddText(PRVM_NAME);
1163 void PRVM_StackTrace(void);
1164 void VM_stackdump (void)
1166 VM_SAFEPARMCOUNT(0, VM_stackdump);
1181 VM_SAFEPARMCOUNT(0, VM_crash);
1183 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1193 void VM_traceon (void)
1195 VM_SAFEPARMCOUNT(0,VM_traceon);
1207 void VM_traceoff (void)
1209 VM_SAFEPARMCOUNT(0,VM_traceoff);
1211 prog->trace = false;
1221 void VM_eprint (void)
1223 VM_SAFEPARMCOUNT(1,VM_eprint);
1225 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1239 VM_SAFEPARMCOUNT(1,VM_rint);
1241 f = PRVM_G_FLOAT(OFS_PARM0);
1243 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1245 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1255 void VM_floor (void)
1257 VM_SAFEPARMCOUNT(1,VM_floor);
1259 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1271 VM_SAFEPARMCOUNT(1,VM_ceil);
1273 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1281 entity nextent(entity)
1284 void VM_nextent (void)
1289 i = PRVM_G_EDICTNUM(OFS_PARM0);
1292 prog->xfunction->builtinsprofile++;
1294 if (i == prog->num_edicts)
1296 VM_RETURN_EDICT(prog->edicts);
1299 ent = PRVM_EDICT_NUM(i);
1300 if (!ent->p.e->free)
1302 VM_RETURN_EDICT(ent);
1309 ===============================================================================
1312 used only for client and menu
1313 severs uses VM_SV_...
1315 Write*(* data, float type, float to)
1317 ===============================================================================
1320 #define MSG_BROADCAST 0 // unreliable to all
1321 #define MSG_ONE 1 // reliable to one (msg_entity)
1322 #define MSG_ALL 2 // reliable to all
1323 #define MSG_INIT 3 // write to the init string
1325 sizebuf_t *VM_WriteDest (void)
1331 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1333 dest = G_FLOAT(OFS_PARM1);
1337 return &sv.datagram;
1340 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1341 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1342 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1344 return &svs.clients[destclient].message;
1347 return &sv.reliable_datagram;
1353 PRVM_ERROR ("WriteDest: bad destination");
1360 void VM_WriteByte (void)
1362 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1365 void VM_WriteChar (void)
1367 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1370 void VM_WriteShort (void)
1372 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1375 void VM_WriteLong (void)
1377 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1380 void VM_WriteAngle (void)
1382 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1385 void VM_WriteCoord (void)
1387 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1390 void VM_WriteString (void)
1392 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1395 void VM_WriteEntity (void)
1397 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1400 //=============================================================================
1407 changelevel(string map)
1410 void VM_changelevel (void)
1414 VM_SAFEPARMCOUNT(1, VM_changelevel);
1418 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1422 // make sure we don't issue two changelevels
1423 if (svs.changelevel_issued)
1425 svs.changelevel_issued = true;
1427 s = G_STRING(OFS_PARM0);
1428 Cbuf_AddText (va("changelevel %s\n",s));
1440 VM_SAFEPARMCOUNT(1,VM_sin);
1441 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1452 VM_SAFEPARMCOUNT(1,VM_cos);
1453 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1465 VM_SAFEPARMCOUNT(1,VM_sqrt);
1466 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1473 Returns a vector of length < 1 and > 0
1478 void VM_randomvec (void)
1483 VM_SAFEPARMCOUNT(0, VM_randomvec);
1488 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1489 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1490 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1492 while (DotProduct(temp, temp) >= 1);
1493 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1496 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1497 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1498 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1499 // length returned always > 0
1500 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1501 VectorScale(temp,length, temp);*/
1502 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1505 //=============================================================================
1511 float registercvar (string name, string value, float flags)
1514 void VM_registercvar (void)
1519 VM_SAFEPARMCOUNT(3,VM_registercvar);
1521 name = PRVM_G_STRING(OFS_PARM0);
1522 value = PRVM_G_STRING(OFS_PARM1);
1523 flags = PRVM_G_FLOAT(OFS_PARM2);
1524 PRVM_G_FLOAT(OFS_RETURN) = 0;
1526 if(flags > CVAR_MAXFLAGSVAL)
1529 // first check to see if it has already been defined
1530 if (Cvar_FindVar (name))
1533 // check for overlap with a command
1534 if (Cmd_Exists (name))
1536 Con_Printf("VM_registercvar: %s is a command\n", name);
1540 Cvar_Get(name, value, flags);
1542 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1549 returns the minimum of two supplied floats
1551 float min(float a, float b, ...[float])
1556 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1557 if (prog->argc == 2)
1558 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1559 else if (prog->argc >= 3)
1562 float f = PRVM_G_FLOAT(OFS_PARM0);
1563 for (i = 1;i < prog->argc;i++)
1564 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1565 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1566 PRVM_G_FLOAT(OFS_RETURN) = f;
1569 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1576 returns the maximum of two supplied floats
1578 float max(float a, float b, ...[float])
1583 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1584 if (prog->argc == 2)
1585 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1586 else if (prog->argc >= 3)
1589 float f = PRVM_G_FLOAT(OFS_PARM0);
1590 for (i = 1;i < prog->argc;i++)
1591 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1592 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1593 G_FLOAT(OFS_RETURN) = f;
1596 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1603 returns number bounded by supplied range
1605 float bound(float min, float value, float max)
1608 void VM_bound (void)
1610 VM_SAFEPARMCOUNT(3,VM_bound);
1611 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1618 returns a raised to power b
1620 float pow(float a, float b)
1625 VM_SAFEPARMCOUNT(2,VM_pow);
1626 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1633 copies data from one entity to another
1635 copyentity(entity src, entity dst)
1638 void VM_copyentity (void)
1640 prvm_edict_t *in, *out;
1641 VM_SAFEPARMCOUNT(2,VM_copyentity);
1642 in = PRVM_G_EDICT(OFS_PARM0);
1643 out = PRVM_G_EDICT(OFS_PARM1);
1644 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1651 sets the color of a client and broadcasts the update to all connected clients
1653 setcolor(clientent, value)
1656 /*void PF_setcolor (void)
1662 entnum = G_EDICTNUM(OFS_PARM0);
1663 i = G_FLOAT(OFS_PARM1);
1665 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1667 Con_Print("tried to setcolor a non-client\n");
1671 client = svs.clients + entnum-1;
1672 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1675 client->old_colors = i;
1676 client->edict->v->team = (i & 15) + 1;
1678 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1679 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1680 MSG_WriteByte (&sv.reliable_datagram, i);
1683 void VM_Files_Init(void)
1685 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1688 void VM_Files_CloseAll(void)
1691 for (i = 0;i < MAX_VMFILES;i++)
1694 FS_Close(VM_FILES[i]);
1695 //VM_FILES[i] = NULL;
1697 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1704 float fopen(string filename, float mode)
1707 // float(string filename, float mode) fopen = #110;
1708 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1709 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1713 char *modestring, *filename;
1715 VM_SAFEPARMCOUNT(2,VM_fopen);
1717 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1718 if (VM_FILES[filenum] == NULL)
1720 if (filenum >= MAX_VMFILES)
1722 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1723 PRVM_G_FLOAT(OFS_RETURN) = -2;
1726 mode = PRVM_G_FLOAT(OFS_PARM1);
1729 case 0: // FILE_READ
1732 case 1: // FILE_APPEND
1735 case 2: // FILE_WRITE
1739 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1740 PRVM_G_FLOAT(OFS_RETURN) = -3;
1743 filename = PRVM_G_STRING(OFS_PARM0);
1744 // .. is parent directory on many platforms
1745 // / is parent directory on Amiga
1746 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1747 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1748 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1750 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1751 PRVM_G_FLOAT(OFS_RETURN) = -4;
1754 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1755 if (VM_FILES[filenum] == NULL && mode == 0)
1756 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1758 if (VM_FILES[filenum] == NULL)
1759 PRVM_G_FLOAT(OFS_RETURN) = -1;
1761 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1768 fclose(float fhandle)
1771 //void(float fhandle) fclose = #111; // closes a file
1772 void VM_fclose(void)
1776 VM_SAFEPARMCOUNT(1,VM_fclose);
1778 filenum = PRVM_G_FLOAT(OFS_PARM0);
1779 if (filenum < 0 || filenum >= MAX_VMFILES)
1781 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1784 if (VM_FILES[filenum] == NULL)
1786 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1789 FS_Close(VM_FILES[filenum]);
1790 VM_FILES[filenum] = NULL;
1797 string fgets(float fhandle)
1800 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1804 static char string[VM_STRINGTEMP_LENGTH];
1807 VM_SAFEPARMCOUNT(1,VM_fgets);
1809 filenum = PRVM_G_FLOAT(OFS_PARM0);
1810 if (filenum < 0 || filenum >= MAX_VMFILES)
1812 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1815 if (VM_FILES[filenum] == NULL)
1817 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1823 c = FS_Getc(VM_FILES[filenum]);
1824 if (c == '\r' || c == '\n' || c < 0)
1826 if (end < VM_STRINGTEMP_LENGTH - 1)
1830 // remove \n following \r
1832 c = FS_Getc(VM_FILES[filenum]);
1833 if (developer.integer)
1834 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1836 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1838 PRVM_G_INT(OFS_RETURN) = 0;
1845 fputs(float fhandle, string s)
1848 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1852 char string[VM_STRINGTEMP_LENGTH];
1855 VM_SAFEPARMCOUNT(2,VM_fputs);
1857 filenum = PRVM_G_FLOAT(OFS_PARM0);
1858 if (filenum < 0 || filenum >= MAX_VMFILES)
1860 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1863 if (VM_FILES[filenum] == NULL)
1865 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1868 VM_VarString(1, string, sizeof(string));
1869 if ((stringlength = strlen(string)))
1870 FS_Write(VM_FILES[filenum], string, stringlength);
1871 if (developer.integer)
1872 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1879 float strlen(string s)
1882 //float(string s) strlen = #114; // returns how many characters are in a string
1883 void VM_strlen(void)
1887 VM_SAFEPARMCOUNT(1,VM_strlen);
1889 s = PRVM_G_STRING(OFS_PARM0);
1891 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1893 PRVM_G_FLOAT(OFS_RETURN) = 0;
1900 string strcat(string,string,...[string])
1903 //string(string s1, string s2) strcat = #115;
1904 // concatenates two strings (for example "abc", "def" would return "abcdef")
1905 // and returns as a tempstring
1906 void VM_strcat(void)
1911 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1913 s = VM_GetTempString();
1914 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1915 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1922 string substring(string s, float start, float length)
1925 // string(string s, float start, float length) substring = #116;
1926 // returns a section of a string as a tempstring
1927 void VM_substring(void)
1929 int i, start, length;
1932 VM_SAFEPARMCOUNT(3,VM_substring);
1934 string = VM_GetTempString();
1935 s = PRVM_G_STRING(OFS_PARM0);
1936 start = PRVM_G_FLOAT(OFS_PARM1);
1937 length = PRVM_G_FLOAT(OFS_PARM2);
1940 for (i = 0;i < start && *s;i++, s++);
1941 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1944 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1951 vector stov(string s)
1954 //vector(string s) stov = #117; // returns vector value from a string
1957 char string[VM_STRINGTEMP_LENGTH];
1959 VM_SAFEPARMCOUNT(1,VM_stov);
1961 VM_VarString(0, string, sizeof(string));
1962 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1969 string strzone(string s)
1972 //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)
1973 void VM_strzone(void)
1977 VM_SAFEPARMCOUNT(1,VM_strzone);
1979 in = PRVM_G_STRING(OFS_PARM0);
1980 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1982 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1992 //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!!!)
1993 void VM_strunzone(void)
1996 VM_SAFEPARMCOUNT(1,VM_strunzone);
1998 str = PRVM_G_STRING(OFS_PARM0);
1999 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2000 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2007 VM_command (used by client and menu)
2009 clientcommand(float client, string s) (for client and menu)
2012 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2013 //this function originally written by KrimZon, made shorter by LordHavoc
2014 void VM_clcommand (void)
2016 client_t *temp_client;
2019 VM_SAFEPARMCOUNT(2,VM_clcommand);
2021 i = PRVM_G_FLOAT(OFS_PARM0);
2022 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2024 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2028 temp_client = host_client;
2029 host_client = svs.clients + i;
2030 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2031 host_client = temp_client;
2039 float tokenize(string s)
2042 //float(string s) tokenize = #441;
2043 // takes apart a string into individal words (access them with argv), returns how many
2044 // this function originally written by KrimZon, made shorter by LordHavoc
2045 static char **tokens = NULL;
2046 static int max_tokens, num_tokens = 0;
2047 void VM_tokenize (void)
2052 VM_SAFEPARMCOUNT(1,VM_tokenize);
2054 str = PRVM_G_STRING(OFS_PARM0);
2059 for (i=0;i<num_tokens;i++)
2065 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2066 max_tokens = strlen(str);
2068 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2070 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2071 strcpy(tokens[num_tokens], com_token);
2074 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2081 string argv(float n)
2084 //string(float n) argv = #442;
2085 // returns a word from the tokenized string (returns nothing for an invalid index)
2086 // this function originally written by KrimZon, made shorter by LordHavoc
2091 VM_SAFEPARMCOUNT(1,VM_argv);
2093 token_num = PRVM_G_FLOAT(OFS_PARM0);
2094 if (token_num >= 0 && token_num < num_tokens)
2095 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2097 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2101 //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)
2102 void PF_setattachment (void)
2104 edict_t *e = G_EDICT(OFS_PARM0);
2105 edict_t *tagentity = G_EDICT(OFS_PARM1);
2106 char *tagname = G_STRING(OFS_PARM2);
2111 if (tagentity == NULL)
2112 tagentity = sv.edicts;
2114 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2116 v->edict = EDICT_TO_PROG(tagentity);
2118 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2121 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2123 modelindex = (int)tagentity->v->modelindex;
2124 if (modelindex >= 0 && modelindex < MAX_MODELS)
2126 model = sv.models[modelindex];
2127 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2128 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2129 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2131 // FIXME: use a model function to get tag info (need to handle skeletal)
2132 if (v->_float == 0 && model->alias.aliasnum_tags)
2133 for (i = 0;i < model->alias.aliasnum_tags;i++)
2134 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2137 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);
2140 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));
2151 void VM_isserver(void)
2153 VM_SAFEPARMCOUNT(0,VM_serverstate);
2155 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2165 void VM_clientcount(void)
2167 VM_SAFEPARMCOUNT(0,VM_clientcount);
2169 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2179 void VM_clientstate(void)
2181 VM_SAFEPARMCOUNT(0,VM_clientstate);
2183 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2190 float getostype(void)
2192 */ // not used at the moment -> not included in the common list
2193 void VM_getostype(void)
2195 VM_SAFEPARMCOUNT(0,VM_getostype);
2200 OS_MAC - not supported
2204 PRVM_G_FLOAT(OFS_RETURN) = 0;
2206 PRVM_G_FLOAT(OFS_RETURN) = 2;
2208 PRVM_G_FLOAT(OFS_RETURN) = 1;
2216 vector getmousepos()
2219 void VM_getmousepos(void)
2222 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2224 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2225 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2226 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2236 void VM_gettime(void)
2238 VM_SAFEPARMCOUNT(0,VM_gettime);
2240 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2247 loadfromdata(string data)
2250 void VM_loadfromdata(void)
2252 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2254 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2258 ========================
2259 VM_M_parseentitydata
2261 parseentitydata(entity ent, string data)
2262 ========================
2264 void VM_M_parseentitydata(void)
2269 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2271 // get edict and test it
2272 ent = PRVM_G_EDICT(OFS_PARM0);
2274 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2276 data = PRVM_G_STRING(OFS_PARM1);
2278 // parse the opening brace
2279 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2280 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2282 PRVM_ED_ParseEdict (data, ent);
2289 loadfromfile(string file)
2292 void VM_loadfromfile(void)
2297 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2299 filename = PRVM_G_STRING(OFS_PARM0);
2300 // .. is parent directory on many platforms
2301 // / is parent directory on Amiga
2302 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2303 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2304 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2306 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2307 PRVM_G_FLOAT(OFS_RETURN) = -4;
2311 // not conform with VM_fopen
2312 data = FS_LoadFile(filename, tempmempool, false);
2314 PRVM_G_FLOAT(OFS_RETURN) = -1;
2316 PRVM_ED_LoadFromFile(data);
2327 float mod(float val, float m)
2330 void VM_modulo(void)
2333 VM_SAFEPARMCOUNT(2,VM_module);
2335 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2336 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2338 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2341 void VM_Search_Init(void)
2343 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2346 void VM_Search_Reset(void)
2349 // reset the fssearch list
2350 for(i = 0; i < MAX_VMSEARCHES; i++)
2351 if(VM_SEARCHLIST[i])
2352 FS_FreeSearch(VM_SEARCHLIST[i]);
2353 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2360 float search_begin(string pattern, float caseinsensitive, float quiet)
2363 void VM_search_begin(void)
2367 int caseinsens, quiet;
2369 VM_SAFEPARMCOUNT(3, VM_search_begin);
2371 pattern = PRVM_G_STRING(OFS_PARM0);
2373 VM_CheckEmptyString(pattern);
2375 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2376 quiet = PRVM_G_FLOAT(OFS_PARM2);
2378 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2379 if(!VM_SEARCHLIST[handle])
2382 if(handle >= MAX_VMSEARCHES)
2384 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2385 PRVM_G_FLOAT(OFS_RETURN) = -2;
2389 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2390 PRVM_G_FLOAT(OFS_RETURN) = -1;
2392 PRVM_G_FLOAT(OFS_RETURN) = handle;
2399 void search_end(float handle)
2402 void VM_search_end(void)
2405 VM_SAFEPARMCOUNT(1, VM_search_end);
2407 handle = PRVM_G_FLOAT(OFS_PARM0);
2409 if(handle < 0 || handle >= MAX_VMSEARCHES)
2411 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2414 if(VM_SEARCHLIST[handle] == NULL)
2416 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2420 FS_FreeSearch(VM_SEARCHLIST[handle]);
2421 VM_SEARCHLIST[handle] = NULL;
2428 float search_getsize(float handle)
2431 void VM_search_getsize(void)
2434 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2436 handle = PRVM_G_FLOAT(OFS_PARM0);
2438 if(handle < 0 || handle >= MAX_VMSEARCHES)
2440 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2443 if(VM_SEARCHLIST[handle] == NULL)
2445 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2449 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2454 VM_search_getfilename
2456 string search_getfilename(float handle, float num)
2459 void VM_search_getfilename(void)
2461 int handle, filenum;
2463 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2465 handle = PRVM_G_FLOAT(OFS_PARM0);
2466 filenum = PRVM_G_FLOAT(OFS_PARM1);
2468 if(handle < 0 || handle >= MAX_VMSEARCHES)
2470 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2473 if(VM_SEARCHLIST[handle] == NULL)
2475 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2478 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2480 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2484 tmp = VM_GetTempString();
2485 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2487 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2494 string chr(float ascii)
2500 VM_SAFEPARMCOUNT(1, VM_chr);
2502 tmp = VM_GetTempString();
2503 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2506 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2509 //=============================================================================
2510 // Draw builtins (client & menu)
2516 float iscachedpic(string pic)
2519 void VM_iscachedpic(void)
2521 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2523 // drawq hasnt such a function, thus always return true
2524 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2531 string precache_pic(string pic)
2534 void VM_precache_pic(void)
2538 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2540 s = PRVM_G_STRING(OFS_PARM0);
2541 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2544 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2546 VM_CheckEmptyString (s);
2548 if(!Draw_CachePic(s))
2549 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2559 void VM_freepic(void)
2563 VM_SAFEPARMCOUNT(1,VM_freepic);
2565 s = PRVM_G_STRING(OFS_PARM0);
2568 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2570 VM_CheckEmptyString (s);
2579 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2582 void VM_drawcharacter(void)
2584 float *pos,*scale,*rgb;
2587 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2589 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2592 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2593 PRVM_G_FLOAT(OFS_RETURN) = -1;
2597 pos = PRVM_G_VECTOR(OFS_PARM0);
2598 scale = PRVM_G_VECTOR(OFS_PARM2);
2599 rgb = PRVM_G_VECTOR(OFS_PARM3);
2600 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2602 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2604 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2605 PRVM_G_FLOAT(OFS_RETURN) = -2;
2609 if(pos[2] || scale[2])
2610 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")));
2612 if(!scale[0] || !scale[1])
2614 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2615 PRVM_G_FLOAT(OFS_RETURN) = -3;
2619 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2620 PRVM_G_FLOAT(OFS_RETURN) = 1;
2627 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2630 void VM_drawstring(void)
2632 float *pos,*scale,*rgb;
2635 VM_SAFEPARMCOUNT(6,VM_drawstring);
2637 string = PRVM_G_STRING(OFS_PARM1);
2640 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2641 PRVM_G_FLOAT(OFS_RETURN) = -1;
2645 VM_CheckEmptyString(string);
2647 pos = PRVM_G_VECTOR(OFS_PARM0);
2648 scale = PRVM_G_VECTOR(OFS_PARM2);
2649 rgb = PRVM_G_VECTOR(OFS_PARM3);
2650 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2652 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2654 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2655 PRVM_G_FLOAT(OFS_RETURN) = -2;
2659 if(!scale[0] || !scale[1])
2661 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2662 PRVM_G_FLOAT(OFS_RETURN) = -3;
2666 if(pos[2] || scale[2])
2667 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")));
2669 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2670 PRVM_G_FLOAT(OFS_RETURN) = 1;
2676 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2679 void VM_drawpic(void)
2682 float *size, *pos, *rgb;
2685 VM_SAFEPARMCOUNT(6,VM_drawpic);
2687 pic = PRVM_G_STRING(OFS_PARM1);
2691 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2692 PRVM_G_FLOAT(OFS_RETURN) = -1;
2696 VM_CheckEmptyString (pic);
2698 // is pic cached ? no function yet for that
2701 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2702 PRVM_G_FLOAT(OFS_RETURN) = -4;
2706 pos = PRVM_G_VECTOR(OFS_PARM0);
2707 size = PRVM_G_VECTOR(OFS_PARM2);
2708 rgb = PRVM_G_VECTOR(OFS_PARM3);
2709 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2711 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2713 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2714 PRVM_G_FLOAT(OFS_RETURN) = -2;
2718 if(pos[2] || size[2])
2719 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")));
2721 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2722 PRVM_G_FLOAT(OFS_RETURN) = 1;
2729 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2732 void VM_drawfill(void)
2734 float *size, *pos, *rgb;
2737 VM_SAFEPARMCOUNT(5,VM_drawfill);
2740 pos = PRVM_G_VECTOR(OFS_PARM0);
2741 size = PRVM_G_VECTOR(OFS_PARM1);
2742 rgb = PRVM_G_VECTOR(OFS_PARM2);
2743 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2745 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2747 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2748 PRVM_G_FLOAT(OFS_RETURN) = -2;
2752 if(pos[2] || size[2])
2753 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")));
2755 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2756 PRVM_G_FLOAT(OFS_RETURN) = 1;
2763 drawsetcliparea(float x, float y, float width, float height)
2766 void VM_drawsetcliparea(void)
2769 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2771 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2772 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2773 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2774 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2776 DrawQ_SetClipArea(x,y,w,h);
2781 VM_drawresetcliparea
2786 void VM_drawresetcliparea(void)
2788 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2790 DrawQ_ResetClipArea();
2797 vector getimagesize(string pic)
2800 void VM_getimagesize(void)
2805 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2807 p = PRVM_G_STRING(OFS_PARM0);
2810 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2812 VM_CheckEmptyString (p);
2814 pic = Draw_CachePic (p);
2816 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2817 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2818 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2821 void VM_Cmd_Init(void)
2823 // only init the stuff for the current prog
2824 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2829 void VM_Cmd_Reset(void)
2831 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2832 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2834 VM_Files_CloseAll();
2837 //============================================================================
2840 char *vm_sv_extensions =
2843 prvm_builtin_t vm_sv_builtins[] = {
2844 0 // to be consistent with the old vm
2847 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2849 void VM_SV_Cmd_Init(void)
2853 void VM_SV_Cmd_Reset(void)
2857 //============================================================================
2860 char *vm_cl_extensions =
2863 prvm_builtin_t vm_cl_builtins[] = {
2864 0 // to be consistent with the old vm
2867 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2869 void VM_CL_Cmd_Init(void)
2873 void VM_CL_Cmd_Reset(void)
2877 //============================================================================
2880 char *vm_m_extensions =
2887 setmousetarget(float target)
2890 void VM_M_setmousetarget(void)
2892 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2894 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2897 in_client_mouse = false;
2900 in_client_mouse = true;
2903 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2911 float getmousetarget
2914 void VM_M_getmousetarget(void)
2916 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2919 PRVM_G_FLOAT(OFS_RETURN) = 2;
2921 PRVM_G_FLOAT(OFS_RETURN) = 1;
2930 setkeydest(float dest)
2933 void VM_M_setkeydest(void)
2935 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2937 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2941 key_dest = key_game;
2945 key_dest = key_menu;
2949 // key_dest = key_message
2952 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2963 void VM_M_getkeydest(void)
2965 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2967 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2971 PRVM_G_FLOAT(OFS_RETURN) = 0;
2974 PRVM_G_FLOAT(OFS_RETURN) = 2;
2978 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2981 PRVM_G_FLOAT(OFS_RETURN) = 3;
2989 callfunction(...,string function_name)
2993 mfunction_t *PRVM_ED_FindFunction (const char *name);
2994 void VM_M_callfunction(void)
3000 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3002 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3005 PRVM_ERROR("VM_M_callfunction: null string !\n");
3007 VM_CheckEmptyString(s);
3009 func = PRVM_ED_FindFunction(s);
3012 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3013 else if (func->first_statement < 0)
3015 // negative statements are built in functions
3016 int builtinnumber = -func->first_statement;
3017 prog->xfunction->builtinsprofile++;
3018 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3019 prog->builtins[builtinnumber]();
3021 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3026 PRVM_ExecuteProgram(func - prog->functions,"");
3035 float isfunction(string function_name)
3038 mfunction_t *PRVM_ED_FindFunction (const char *name);
3039 void VM_M_isfunction(void)
3044 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3046 s = PRVM_G_STRING(OFS_PARM0);
3049 PRVM_ERROR("VM_M_isfunction: null string !\n");
3051 VM_CheckEmptyString(s);
3053 func = PRVM_ED_FindFunction(s);
3056 PRVM_G_FLOAT(OFS_RETURN) = false;
3058 PRVM_G_FLOAT(OFS_RETURN) = true;
3065 writetofile(float fhandle, entity ent)
3068 void VM_M_writetofile(void)
3073 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3075 filenum = PRVM_G_FLOAT(OFS_PARM0);
3076 if (filenum < 0 || filenum >= MAX_VMFILES)
3078 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3081 if (VM_FILES[filenum] == NULL)
3083 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3087 ent = PRVM_G_EDICT(OFS_PARM1);
3090 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3094 PRVM_ED_Write (VM_FILES[filenum], ent);
3101 vector getresolution(float number)
3104 extern unsigned short video_resolutions[][2];
3105 void VM_M_getresolution(void)
3108 VM_SAFEPARMCOUNT(1, VM_getresolution);
3110 nr = PRVM_G_FLOAT(OFS_PARM0);
3113 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3114 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3115 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3122 string keynumtostring(float keynum)
3125 void VM_M_keynumtostring(void)
3129 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3131 keynum = PRVM_G_FLOAT(OFS_PARM0);
3133 tmp = VM_GetTempString();
3135 strcpy(tmp, Key_KeynumToString(keynum));
3137 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3142 VM_M_findkeysforcommand
3144 string findkeysforcommand(string command)
3146 the returned string is an altstring
3149 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3151 void M_FindKeysForCommand(char *command, int *keys);
3152 void VM_M_findkeysforcommand(void)
3158 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3160 cmd = PRVM_G_STRING(OFS_PARM0);
3162 VM_CheckEmptyString(cmd);
3164 (ret = VM_GetTempString())[0] = 0;
3166 M_FindKeysForCommand(cmd, keys);
3168 for(i = 0; i < NUMKEYS; i++)
3169 ret = strcat(ret, va(" \'%i\'", keys[i]));
3171 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3176 VM_M_gethostcachecount
3178 float gethostcachevalue(float type)
3189 void VM_M_gethostcachevalue( void )
3192 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3194 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3196 type = PRVM_G_FLOAT( OFS_PARM0 );
3197 if( type < 0 || type > 4 )
3198 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3202 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3205 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3208 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3211 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3214 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3221 VM_M_gethostcachestring
3223 string gethostcachestring(float type, float hostnr)
3231 void VM_M_gethostcachestring(void)
3236 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3238 PRVM_G_INT(OFS_RETURN) = 0;
3240 type = PRVM_G_FLOAT(OFS_PARM0);
3242 if(type < 0 || type > 2)
3244 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3248 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3250 if(hostnr < 0 || hostnr >= hostCacheCount)
3252 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3257 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3258 else if( type == 1 )
3259 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3261 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3264 prvm_builtin_t vm_m_builtins[] = {
3265 0, // to be consistent with the old vm
3266 // common builtings (mostly)
3343 VM_search_getfilename, // 77
3360 VM_WriteEntity, // 408
3376 VM_drawresetcliparea,
3377 VM_getimagesize,// 460
3386 VM_M_setmousetarget,
3387 VM_M_getmousetarget,
3392 VM_M_keynumtostring,
3393 VM_M_findkeysforcommand,// 610
3394 VM_M_gethostcachevalue,
3395 VM_M_gethostcachestring,
3396 VM_M_parseentitydata // 613
3399 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3401 void VM_M_Cmd_Init(void)
3406 void VM_M_Cmd_Reset(void)