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"
153 #include "clprogdefs.h"
154 #include "mprogdefs.h"
156 //============================================================================
157 // nice helper macros
159 #ifndef VM_NOPARMCHECK
160 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
162 #define VM_SAFEPARMCOUNT(p,f)
165 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
167 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
169 #define e10 0,0,0,0,0,0,0,0,0,0
170 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
171 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
173 //============================================================================
176 // string zone mempool
177 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
179 // temp string handling
180 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
181 #define VM_STRINGTEMP_BUFFERS 16
182 #define VM_STRINGTEMP_LENGTH 4096
183 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
184 static int vm_string_tempindex = 0;
187 #define MAX_VMFILES 256
188 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
189 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
191 qfile_t *vm_files[MAX_PRVMFILES];
193 // qc fs search handling
194 #define MAX_VMSEARCHES 128
195 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
196 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
198 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
200 static char *VM_GetTempString(void)
203 s = vm_string_temp[vm_string_tempindex];
204 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
208 void VM_CheckEmptyString (char *s)
211 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
214 //============================================================================
217 void VM_VarString(int first, char *out, int outlength)
223 outend = out + outlength - 1;
224 for (i = first;i < prog->argc && out < outend;i++)
226 s = PRVM_G_STRING((OFS_PARM0+i*3));
227 while (out < outend && *s)
237 returns true if the extension is supported by the server
239 checkextension(extensionname)
243 // kind of helper function
244 static qboolean checkextension(char *name)
250 for (e = prog->extensionstring;*e;e++)
257 while (*e && *e != ' ')
259 if (e - start == len)
260 if (!strncasecmp(start, name, len))
268 void VM_checkextension (void)
270 VM_SAFEPARMCOUNT(1,VM_checkextension);
272 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
279 This is a TERMINAL error, which will kill off the entire prog.
288 char string[VM_STRINGTEMP_LENGTH];
290 VM_VarString(0, string, sizeof(string));
291 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
294 ed = PRVM_G_EDICT(prog->self->ofs);
298 PRVM_ERROR ("%s: Program error", PRVM_NAME);
305 Dumps out self, then an error message. The program is aborted and self is
306 removed, but the level can continue.
311 void VM_objerror (void)
314 char string[VM_STRINGTEMP_LENGTH];
316 VM_VarString(0, string, sizeof(string));
317 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
320 ed = PRVM_G_EDICT (prog->self->ofs);
326 // objerror has to display the object fields -> else call
327 PRVM_ERROR ("VM_objecterror: self not defined !\n");
332 VM_print (actually used only by client and menu)
341 char string[VM_STRINGTEMP_LENGTH];
343 VM_VarString(0, string, sizeof(string));
351 broadcast print to everyone on server
356 void VM_bprint (void)
358 char string[VM_STRINGTEMP_LENGTH];
362 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
366 VM_VarString(0, string, sizeof(string));
367 SV_BroadcastPrint(string);
372 VM_sprint (menu & client but only if server.active == true)
374 single print to a specific client
376 sprint(float clientnum,...[string])
379 void VM_sprint (void)
383 char string[VM_STRINGTEMP_LENGTH];
385 //find client for this entity
386 clientnum = PRVM_G_FLOAT(OFS_PARM0);
387 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
389 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
393 client = svs.clients + clientnum;
394 if (!client->netconnection)
396 VM_VarString(1, string, sizeof(string));
397 MSG_WriteChar(&client->message,svc_print);
398 MSG_WriteString(&client->message, string);
405 single print to the screen
407 centerprint(clientent, value)
410 void VM_centerprint (void)
412 char string[VM_STRINGTEMP_LENGTH];
414 VM_VarString(0, string, sizeof(string));
415 SCR_CenterPrint(string);
422 vector normalize(vector)
425 void VM_normalize (void)
431 VM_SAFEPARMCOUNT(1,VM_normalize);
433 value1 = PRVM_G_VECTOR(OFS_PARM0);
435 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
439 newvalue[0] = newvalue[1] = newvalue[2] = 0;
443 newvalue[0] = value1[0] * new;
444 newvalue[1] = value1[1] * new;
445 newvalue[2] = value1[2] * new;
448 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
463 VM_SAFEPARMCOUNT(1,VM_vlen);
465 value1 = PRVM_G_VECTOR(OFS_PARM0);
467 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
470 PRVM_G_FLOAT(OFS_RETURN) = new;
477 float vectoyaw(vector)
480 void VM_vectoyaw (void)
485 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
487 value1 = PRVM_G_VECTOR(OFS_PARM0);
489 if (value1[1] == 0 && value1[0] == 0)
493 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
498 PRVM_G_FLOAT(OFS_RETURN) = yaw;
506 vector vectoangles(vector)
509 void VM_vectoangles (void)
515 VM_SAFEPARMCOUNT(1,VM_vectoangles);
517 value1 = PRVM_G_VECTOR(OFS_PARM0);
519 if (value1[1] == 0 && value1[0] == 0)
529 // LordHavoc: optimized a bit
532 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
536 else if (value1[1] > 0)
541 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
542 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
547 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
548 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
549 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
556 Returns a number from 0<= num < 1
561 void VM_random (void)
565 VM_SAFEPARMCOUNT(0,VM_random);
567 num = (rand ()&0x7fff) / ((float)0x7fff);
569 PRVM_G_FLOAT(OFS_RETURN) = num;
576 Each entity can have eight independant sound sources, like voice,
579 Channel 0 is an auto-allocate channel, the others override anything
580 already running on that entity/channel pair.
582 An attenuation of 0 will play full volume everywhere in the level.
583 Larger attenuations will drop off.
596 entity = G_EDICT(OFS_PARM0);
597 channel = G_FLOAT(OFS_PARM1);
598 sample = G_STRING(OFS_PARM2);
599 volume = G_FLOAT(OFS_PARM3) * 255;
600 attenuation = G_FLOAT(OFS_PARM4);
602 if (volume < 0 || volume > 255)
603 Host_Error ("SV_StartSound: volume = %i", volume);
605 if (attenuation < 0 || attenuation > 4)
606 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
608 if (channel < 0 || channel > 7)
609 Host_Error ("SV_StartSound: channel = %i", channel);
611 SV_StartSound (entity, channel, sample, volume, attenuation);
619 localsound(string sample)
622 void VM_localsound(void)
626 VM_SAFEPARMCOUNT(1,VM_localsound);
628 s = PRVM_G_STRING(OFS_PARM0);
630 if(!S_LocalSound (s))
632 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
633 PRVM_G_FLOAT(OFS_RETURN) = -4;
637 PRVM_G_FLOAT(OFS_RETURN) = 1;
649 PRVM_ERROR ("%s: break statement", PRVM_NAME);
652 //============================================================================
658 Sends text over to the client's execution buffer
660 [localcmd (string) or]
664 void VM_localcmd (void)
666 VM_SAFEPARMCOUNT(1,VM_localcmd);
668 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
680 VM_SAFEPARMCOUNT(1,VM_cvar);
682 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
689 const string str_cvar (string)
692 void VM_str_cvar(void)
695 const char *cvar_string;
696 VM_SAFEPARMCOUNT(1,VM_str_cvar);
698 name = PRVM_G_STRING(OFS_PARM0);
701 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
703 VM_CheckEmptyString(name);
705 out = VM_GetTempString();
707 cvar_string = Cvar_VariableString(name);
709 strcpy(out, cvar_string);
711 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
718 void cvar_set (string,string)
721 void VM_cvar_set (void)
723 VM_SAFEPARMCOUNT(2,VM_cvar_set);
725 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
735 void VM_dprint (void)
737 char string[VM_STRINGTEMP_LENGTH];
738 if (developer.integer)
740 VM_VarString(0, string, sizeof(string));
741 Con_Printf("%s: %s", PRVM_NAME, string);
758 VM_SAFEPARMCOUNT(1, VM_ftos);
760 v = PRVM_G_FLOAT(OFS_PARM0);
762 s = VM_GetTempString();
763 if ((float)((int)v) == v)
764 sprintf(s, "%i", (int)v);
767 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
782 VM_SAFEPARMCOUNT(1,VM_fabs);
784 v = PRVM_G_FLOAT(OFS_PARM0);
785 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
800 VM_SAFEPARMCOUNT(1,VM_vtos);
802 s = VM_GetTempString();
803 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]);
804 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
819 VM_SAFEPARMCOUNT(1, VM_etos);
821 s = VM_GetTempString();
822 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
823 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
830 float stof(...[string])
835 char string[VM_STRINGTEMP_LENGTH];
836 VM_VarString(0, string, sizeof(string));
837 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
841 ========================
845 ========================
849 VM_SAFEPARMCOUNT(1, VM_itof);
850 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
854 ========================
858 ========================
863 VM_SAFEPARMCOUNT(1, VM_ftoi);
865 ent = PRVM_G_FLOAT(OFS_PARM0);
866 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
867 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
869 PRVM_G_INT(OFS_RETURN) = ent;
883 prog->xfunction->builtinsprofile += 20;
884 ed = PRVM_ED_Alloc();
896 void VM_remove (void)
899 prog->xfunction->builtinsprofile += 20;
901 VM_SAFEPARMCOUNT(1, VM_remove);
903 ed = PRVM_G_EDICT(OFS_PARM0);
904 // if (ed == prog->edicts)
905 // PRVM_ERROR ("remove: tried to remove world\n");
906 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
907 // Host_Error("remove: tried to remove a client\n");
915 entity find(entity start, .string field, string match)
926 VM_SAFEPARMCOUNT(3,VM_find);
928 e = PRVM_G_EDICTNUM(OFS_PARM0);
929 f = PRVM_G_INT(OFS_PARM1);
930 s = PRVM_G_STRING(OFS_PARM2);
934 // return reserved edict 0 (could be used for whatever the prog wants)
935 VM_RETURN_EDICT(prog->edicts);
939 for (e++ ; e < prog->num_edicts ; e++)
941 prog->xfunction->builtinsprofile++;
942 ed = PRVM_EDICT_NUM(e);
945 t = PRVM_E_STRING(ed,f);
955 VM_RETURN_EDICT(prog->edicts);
962 entity findfloat(entity start, .float field, float match)
963 entity findentity(entity start, .entity field, entity match)
966 // LordHavoc: added this for searching float, int, and entity reference fields
967 void VM_findfloat (void)
974 VM_SAFEPARMCOUNT(3,VM_findfloat);
976 e = PRVM_G_EDICTNUM(OFS_PARM0);
977 f = PRVM_G_INT(OFS_PARM1);
978 s = PRVM_G_FLOAT(OFS_PARM2);
980 for (e++ ; e < prog->num_edicts ; e++)
982 prog->xfunction->builtinsprofile++;
983 ed = PRVM_EDICT_NUM(e);
986 if (PRVM_E_FLOAT(ed,f) == s)
993 VM_RETURN_EDICT(prog->edicts);
1000 entity findchain(.string field, string match)
1003 int PRVM_ED_FindFieldOffset(const char *field);
1004 // chained search for strings in entity fields
1005 // entity(.string field, string match) findchain = #402;
1006 void VM_findchain (void)
1012 prvm_edict_t *ent, *chain;
1014 VM_SAFEPARMCOUNT(2,VM_findchain);
1016 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1017 if(!prog->flag & PRVM_FE_CHAIN)
1018 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1020 chain_of = PRVM_ED_FindFieldOffset ("chain");
1022 chain = prog->edicts;
1024 f = PRVM_G_INT(OFS_PARM0);
1025 s = PRVM_G_STRING(OFS_PARM1);
1028 VM_RETURN_EDICT(prog->edicts);
1032 ent = PRVM_NEXT_EDICT(prog->edicts);
1033 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1035 prog->xfunction->builtinsprofile++;
1038 t = PRVM_E_STRING(ent,f);
1044 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1048 VM_RETURN_EDICT(chain);
1055 entity findchainfloat(.string field, float match)
1056 entity findchainentity(.string field, entity match)
1059 // LordHavoc: chained search for float, int, and entity reference fields
1060 // entity(.string field, float match) findchainfloat = #403;
1061 void VM_findchainfloat (void)
1067 prvm_edict_t *ent, *chain;
1069 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1071 if(!prog->flag & PRVM_FE_CHAIN)
1072 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1074 chain_of = PRVM_ED_FindFieldOffset ("chain");
1076 chain = (prvm_edict_t *)prog->edicts;
1078 f = PRVM_G_INT(OFS_PARM0);
1079 s = PRVM_G_FLOAT(OFS_PARM1);
1081 ent = PRVM_NEXT_EDICT(prog->edicts);
1082 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1084 prog->xfunction->builtinsprofile++;
1087 if (E_FLOAT(ent,f) != s)
1090 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1094 VM_RETURN_EDICT(chain);
1101 string precache_file(string)
1104 void VM_precache_file (void)
1105 { // precache_file is only used to copy files with qcc, it does nothing
1106 VM_SAFEPARMCOUNT(1,VM_precache_file);
1108 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1115 used instead of the other VM_precache_* functions in the builtin list
1119 void VM_precache_error (void)
1121 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1128 string precache_sound (string sample)
1131 void VM_precache_sound (void)
1135 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1137 s = PRVM_G_STRING(OFS_PARM0);
1138 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1139 VM_CheckEmptyString (s);
1141 if(!S_PrecacheSound (s,true, true))
1142 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1152 void VM_coredump (void)
1154 VM_SAFEPARMCOUNT(0,VM_coredump);
1156 Cbuf_AddText("prvm_edicts ");
1157 Cbuf_AddText(PRVM_NAME);
1168 void PRVM_StackTrace(void);
1169 void VM_stackdump (void)
1171 VM_SAFEPARMCOUNT(0, VM_stackdump);
1186 VM_SAFEPARMCOUNT(0, VM_crash);
1188 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1198 void VM_traceon (void)
1200 VM_SAFEPARMCOUNT(0,VM_traceon);
1212 void VM_traceoff (void)
1214 VM_SAFEPARMCOUNT(0,VM_traceoff);
1216 prog->trace = false;
1226 void VM_eprint (void)
1228 VM_SAFEPARMCOUNT(1,VM_eprint);
1230 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1244 VM_SAFEPARMCOUNT(1,VM_rint);
1246 f = PRVM_G_FLOAT(OFS_PARM0);
1248 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1250 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1260 void VM_floor (void)
1262 VM_SAFEPARMCOUNT(1,VM_floor);
1264 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1276 VM_SAFEPARMCOUNT(1,VM_ceil);
1278 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1286 entity nextent(entity)
1289 void VM_nextent (void)
1294 i = PRVM_G_EDICTNUM(OFS_PARM0);
1297 prog->xfunction->builtinsprofile++;
1299 if (i == prog->num_edicts)
1301 VM_RETURN_EDICT(prog->edicts);
1304 ent = PRVM_EDICT_NUM(i);
1305 if (!ent->p.e->free)
1307 VM_RETURN_EDICT(ent);
1314 ===============================================================================
1317 used only for client and menu
1318 severs uses VM_SV_...
1320 Write*(* data, float type, float to)
1322 ===============================================================================
1325 #define MSG_BROADCAST 0 // unreliable to all
1326 #define MSG_ONE 1 // reliable to one (msg_entity)
1327 #define MSG_ALL 2 // reliable to all
1328 #define MSG_INIT 3 // write to the init string
1330 sizebuf_t *VM_WriteDest (void)
1336 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1338 dest = G_FLOAT(OFS_PARM1);
1342 return &sv.datagram;
1345 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1346 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1347 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1349 return &svs.clients[destclient].message;
1352 return &sv.reliable_datagram;
1358 PRVM_ERROR ("WriteDest: bad destination");
1365 void VM_WriteByte (void)
1367 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1370 void VM_WriteChar (void)
1372 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1375 void VM_WriteShort (void)
1377 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1380 void VM_WriteLong (void)
1382 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1385 void VM_WriteAngle (void)
1387 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1390 void VM_WriteCoord (void)
1392 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1395 void VM_WriteString (void)
1397 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1400 void VM_WriteEntity (void)
1402 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1405 //=============================================================================
1412 changelevel(string map)
1415 void VM_changelevel (void)
1419 VM_SAFEPARMCOUNT(1, VM_changelevel);
1423 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1427 // make sure we don't issue two changelevels
1428 if (svs.changelevel_issued)
1430 svs.changelevel_issued = true;
1432 s = G_STRING(OFS_PARM0);
1433 Cbuf_AddText (va("changelevel %s\n",s));
1445 VM_SAFEPARMCOUNT(1,VM_sin);
1446 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1457 VM_SAFEPARMCOUNT(1,VM_cos);
1458 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1470 VM_SAFEPARMCOUNT(1,VM_sqrt);
1471 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1478 Returns a vector of length < 1 and > 0
1483 void VM_randomvec (void)
1488 VM_SAFEPARMCOUNT(0, VM_randomvec);
1493 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1494 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1495 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1497 while (DotProduct(temp, temp) >= 1);
1498 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1501 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1502 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1503 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1504 // length returned always > 0
1505 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1506 VectorScale(temp,length, temp);*/
1507 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1510 //=============================================================================
1516 float registercvar (string name, string value, float flags)
1519 void VM_registercvar (void)
1524 VM_SAFEPARMCOUNT(3,VM_registercvar);
1526 name = PRVM_G_STRING(OFS_PARM0);
1527 value = PRVM_G_STRING(OFS_PARM1);
1528 flags = PRVM_G_FLOAT(OFS_PARM2);
1529 PRVM_G_FLOAT(OFS_RETURN) = 0;
1531 if(flags > CVAR_MAXFLAGSVAL)
1534 // first check to see if it has already been defined
1535 if (Cvar_FindVar (name))
1538 // check for overlap with a command
1539 if (Cmd_Exists (name))
1541 Con_Printf("VM_registercvar: %s is a command\n", name);
1545 Cvar_Get(name, value, 0);
1547 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1554 returns the minimum of two supplied floats
1556 float min(float a, float b, ...[float])
1561 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1562 if (prog->argc == 2)
1563 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1564 else if (prog->argc >= 3)
1567 float f = PRVM_G_FLOAT(OFS_PARM0);
1568 for (i = 1;i < prog->argc;i++)
1569 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1570 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1571 PRVM_G_FLOAT(OFS_RETURN) = f;
1574 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1581 returns the maximum of two supplied floats
1583 float max(float a, float b, ...[float])
1588 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1589 if (prog->argc == 2)
1590 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1591 else if (prog->argc >= 3)
1594 float f = PRVM_G_FLOAT(OFS_PARM0);
1595 for (i = 1;i < prog->argc;i++)
1596 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1597 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1598 G_FLOAT(OFS_RETURN) = f;
1601 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1608 returns number bounded by supplied range
1610 float bound(float min, float value, float max)
1613 void VM_bound (void)
1615 VM_SAFEPARMCOUNT(3,VM_bound);
1616 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1623 returns a raised to power b
1625 float pow(float a, float b)
1630 VM_SAFEPARMCOUNT(2,VM_pow);
1631 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1638 copies data from one entity to another
1640 copyentity(entity src, entity dst)
1643 void VM_copyentity (void)
1645 prvm_edict_t *in, *out;
1646 VM_SAFEPARMCOUNT(2,VM_copyentity);
1647 in = PRVM_G_EDICT(OFS_PARM0);
1648 out = PRVM_G_EDICT(OFS_PARM1);
1649 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1656 sets the color of a client and broadcasts the update to all connected clients
1658 setcolor(clientent, value)
1661 /*void PF_setcolor (void)
1667 entnum = G_EDICTNUM(OFS_PARM0);
1668 i = G_FLOAT(OFS_PARM1);
1670 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1672 Con_Print("tried to setcolor a non-client\n");
1676 client = svs.clients + entnum-1;
1677 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1680 client->old_colors = i;
1681 client->edict->v->team = (i & 15) + 1;
1683 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1684 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1685 MSG_WriteByte (&sv.reliable_datagram, i);
1688 void VM_Files_Init(void)
1690 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1693 void VM_Files_CloseAll(void)
1696 for (i = 0;i < MAX_VMFILES;i++)
1699 FS_Close(VM_FILES[i]);
1700 //VM_FILES[i] = NULL;
1702 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1709 float fopen(string filename, float mode)
1712 // float(string filename, float mode) fopen = #110;
1713 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1714 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1718 char *modestring, *filename;
1720 VM_SAFEPARMCOUNT(2,VM_fopen);
1722 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1723 if (VM_FILES[filenum] == NULL)
1725 if (filenum >= MAX_VMFILES)
1727 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1728 PRVM_G_FLOAT(OFS_RETURN) = -2;
1731 mode = PRVM_G_FLOAT(OFS_PARM1);
1734 case 0: // FILE_READ
1737 case 1: // FILE_APPEND
1740 case 2: // FILE_WRITE
1744 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1745 PRVM_G_FLOAT(OFS_RETURN) = -3;
1748 filename = PRVM_G_STRING(OFS_PARM0);
1749 // .. is parent directory on many platforms
1750 // / is parent directory on Amiga
1751 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1752 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1753 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1755 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1756 PRVM_G_FLOAT(OFS_RETURN) = -4;
1759 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1760 if (VM_FILES[filenum] == NULL && mode == 0)
1761 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1763 if (VM_FILES[filenum] == NULL)
1764 PRVM_G_FLOAT(OFS_RETURN) = -1;
1766 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1773 fclose(float fhandle)
1776 //void(float fhandle) fclose = #111; // closes a file
1777 void VM_fclose(void)
1781 VM_SAFEPARMCOUNT(1,VM_fclose);
1783 filenum = PRVM_G_FLOAT(OFS_PARM0);
1784 if (filenum < 0 || filenum >= MAX_VMFILES)
1786 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1789 if (VM_FILES[filenum] == NULL)
1791 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1794 FS_Close(VM_FILES[filenum]);
1795 VM_FILES[filenum] = NULL;
1802 string fgets(float fhandle)
1805 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1809 static char string[VM_STRINGTEMP_LENGTH];
1812 VM_SAFEPARMCOUNT(1,VM_fgets);
1814 filenum = PRVM_G_FLOAT(OFS_PARM0);
1815 if (filenum < 0 || filenum >= MAX_VMFILES)
1817 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1820 if (VM_FILES[filenum] == NULL)
1822 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1828 c = FS_Getc(VM_FILES[filenum]);
1829 if (c == '\r' || c == '\n' || c < 0)
1831 if (end < VM_STRINGTEMP_LENGTH - 1)
1835 // remove \n following \r
1837 c = FS_Getc(VM_FILES[filenum]);
1838 if (developer.integer)
1839 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1841 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1843 PRVM_G_INT(OFS_RETURN) = 0;
1850 fputs(float fhandle, string s)
1853 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1857 char string[VM_STRINGTEMP_LENGTH];
1860 VM_SAFEPARMCOUNT(2,VM_fputs);
1862 filenum = PRVM_G_FLOAT(OFS_PARM0);
1863 if (filenum < 0 || filenum >= MAX_VMFILES)
1865 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1868 if (VM_FILES[filenum] == NULL)
1870 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1873 VM_VarString(1, string, sizeof(string));
1874 if ((stringlength = strlen(string)))
1875 FS_Write(VM_FILES[filenum], string, stringlength);
1876 if (developer.integer)
1877 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1884 float strlen(string s)
1887 //float(string s) strlen = #114; // returns how many characters are in a string
1888 void VM_strlen(void)
1892 VM_SAFEPARMCOUNT(1,VM_strlen);
1894 s = PRVM_G_STRING(OFS_PARM0);
1896 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1898 PRVM_G_FLOAT(OFS_RETURN) = 0;
1905 string strcat(string,string,...[string])
1908 //string(string s1, string s2) strcat = #115;
1909 // concatenates two strings (for example "abc", "def" would return "abcdef")
1910 // and returns as a tempstring
1911 void VM_strcat(void)
1916 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1918 s = VM_GetTempString();
1919 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1920 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1927 string substring(string s, float start, float length)
1930 // string(string s, float start, float length) substring = #116;
1931 // returns a section of a string as a tempstring
1932 void VM_substring(void)
1934 int i, start, length;
1937 VM_SAFEPARMCOUNT(3,VM_substring);
1939 string = VM_GetTempString();
1940 s = PRVM_G_STRING(OFS_PARM0);
1941 start = PRVM_G_FLOAT(OFS_PARM1);
1942 length = PRVM_G_FLOAT(OFS_PARM2);
1945 for (i = 0;i < start && *s;i++, s++);
1946 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1949 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1956 vector stov(string s)
1959 //vector(string s) stov = #117; // returns vector value from a string
1962 char string[VM_STRINGTEMP_LENGTH];
1964 VM_SAFEPARMCOUNT(1,VM_stov);
1966 VM_VarString(0, string, sizeof(string));
1967 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1974 string strzone(string s)
1977 //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)
1978 void VM_strzone(void)
1982 VM_SAFEPARMCOUNT(1,VM_strzone);
1984 in = PRVM_G_STRING(OFS_PARM0);
1985 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1987 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1997 //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!!!)
1998 void VM_strunzone(void)
2001 VM_SAFEPARMCOUNT(1,VM_strunzone);
2003 str = PRVM_G_STRING(OFS_PARM0);
2004 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2005 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2012 VM_command (used by client and menu)
2014 clientcommand(float client, string s) (for client and menu)
2017 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2018 //this function originally written by KrimZon, made shorter by LordHavoc
2019 void VM_clcommand (void)
2021 client_t *temp_client;
2024 VM_SAFEPARMCOUNT(2,VM_clcommand);
2026 i = PRVM_G_FLOAT(OFS_PARM0);
2027 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2029 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2033 temp_client = host_client;
2034 host_client = svs.clients + i;
2035 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2036 host_client = temp_client;
2044 float tokenize(string s)
2047 //float(string s) tokenize = #441;
2048 // takes apart a string into individal words (access them with argv), returns how many
2049 // this function originally written by KrimZon, made shorter by LordHavoc
2050 static char **tokens = NULL;
2051 static int max_tokens, num_tokens = 0;
2052 void VM_tokenize (void)
2057 VM_SAFEPARMCOUNT(1,VM_tokenize);
2059 str = PRVM_G_STRING(OFS_PARM0);
2064 for (i=0;i<num_tokens;i++)
2070 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2071 max_tokens = strlen(str);
2073 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2075 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2076 strcpy(tokens[num_tokens], com_token);
2079 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2086 string argv(float n)
2089 //string(float n) argv = #442;
2090 // returns a word from the tokenized string (returns nothing for an invalid index)
2091 // this function originally written by KrimZon, made shorter by LordHavoc
2096 VM_SAFEPARMCOUNT(1,VM_argv);
2098 token_num = PRVM_G_FLOAT(OFS_PARM0);
2099 if (token_num >= 0 && token_num < num_tokens)
2100 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2102 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2106 //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)
2107 void PF_setattachment (void)
2109 edict_t *e = G_EDICT(OFS_PARM0);
2110 edict_t *tagentity = G_EDICT(OFS_PARM1);
2111 char *tagname = G_STRING(OFS_PARM2);
2116 if (tagentity == NULL)
2117 tagentity = sv.edicts;
2119 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2121 v->edict = EDICT_TO_PROG(tagentity);
2123 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2126 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2128 modelindex = (int)tagentity->v->modelindex;
2129 if (modelindex >= 0 && modelindex < MAX_MODELS)
2131 model = sv.models[modelindex];
2132 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2133 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2134 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2136 // FIXME: use a model function to get tag info (need to handle skeletal)
2137 if (v->_float == 0 && model->alias.aliasnum_tags)
2138 for (i = 0;i < model->alias.aliasnum_tags;i++)
2139 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2142 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);
2145 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));
2156 void VM_isserver(void)
2158 VM_SAFEPARMCOUNT(0,VM_serverstate);
2160 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2170 void VM_clientcount(void)
2172 VM_SAFEPARMCOUNT(0,VM_clientcount);
2174 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2184 void VM_clientstate(void)
2186 VM_SAFEPARMCOUNT(0,VM_clientstate);
2188 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2195 float getostype(void)
2197 */ // not used at the moment -> not included in the common list
2198 void VM_getostype(void)
2200 VM_SAFEPARMCOUNT(0,VM_getostype);
2205 OS_MAC - not supported
2209 PRVM_G_FLOAT(OFS_RETURN) = 0;
2211 PRVM_G_FLOAT(OFS_RETURN) = 2;
2213 PRVM_G_FLOAT(OFS_RETURN) = 1;
2221 vector getmousepos()
2224 void VM_getmousepos(void)
2227 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2229 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2230 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2231 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2241 void VM_gettime(void)
2243 VM_SAFEPARMCOUNT(0,VM_gettime);
2245 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2252 loadfromdata(string data)
2255 void VM_loadfromdata(void)
2257 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2259 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2263 ========================
2264 VM_M_parseentitydata
2266 parseentitydata(entity ent, string data)
2267 ========================
2269 void VM_M_parseentitydata(void)
2274 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2276 // get edict and test it
2277 ent = PRVM_G_EDICT(OFS_PARM0);
2279 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2281 data = PRVM_G_STRING(OFS_PARM1);
2283 // parse the opening brace
2284 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2285 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2287 PRVM_ED_ParseEdict (data, ent);
2294 loadfromfile(string file)
2297 void VM_loadfromfile(void)
2302 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2304 filename = PRVM_G_STRING(OFS_PARM0);
2305 // .. is parent directory on many platforms
2306 // / is parent directory on Amiga
2307 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2308 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2309 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2311 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2312 PRVM_G_FLOAT(OFS_RETURN) = -4;
2316 // not conform with VM_fopen
2317 data = FS_LoadFile(filename, tempmempool, false);
2319 PRVM_G_FLOAT(OFS_RETURN) = -1;
2321 PRVM_ED_LoadFromFile(data);
2332 float mod(float val, float m)
2335 void VM_modulo(void)
2338 VM_SAFEPARMCOUNT(2,VM_module);
2340 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2341 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2343 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2346 void VM_Search_Init(void)
2348 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2351 void VM_Search_Reset(void)
2354 // reset the fssearch list
2355 for(i = 0; i < MAX_VMSEARCHES; i++)
2356 if(VM_SEARCHLIST[i])
2357 FS_FreeSearch(VM_SEARCHLIST[i]);
2358 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2365 float search_begin(string pattern, float caseinsensitive, float quiet)
2368 void VM_search_begin(void)
2372 int caseinsens, quiet;
2374 VM_SAFEPARMCOUNT(3, VM_search_begin);
2376 pattern = PRVM_G_STRING(OFS_PARM0);
2378 VM_CheckEmptyString(pattern);
2380 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2381 quiet = PRVM_G_FLOAT(OFS_PARM2);
2383 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2384 if(!VM_SEARCHLIST[handle])
2387 if(handle >= MAX_VMSEARCHES)
2389 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2390 PRVM_G_FLOAT(OFS_RETURN) = -2;
2394 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2395 PRVM_G_FLOAT(OFS_RETURN) = -1;
2397 PRVM_G_FLOAT(OFS_RETURN) = handle;
2404 void search_end(float handle)
2407 void VM_search_end(void)
2410 VM_SAFEPARMCOUNT(1, VM_search_end);
2412 handle = PRVM_G_FLOAT(OFS_PARM0);
2414 if(handle < 0 || handle >= MAX_VMSEARCHES)
2416 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2419 if(VM_SEARCHLIST[handle] == NULL)
2421 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2425 FS_FreeSearch(VM_SEARCHLIST[handle]);
2426 VM_SEARCHLIST[handle] = NULL;
2433 float search_getsize(float handle)
2436 void VM_search_getsize(void)
2439 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2441 handle = PRVM_G_FLOAT(OFS_PARM0);
2443 if(handle < 0 || handle >= MAX_VMSEARCHES)
2445 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2448 if(VM_SEARCHLIST[handle] == NULL)
2450 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2454 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2459 VM_search_getfilename
2461 string search_getfilename(float handle, float num)
2464 void VM_search_getfilename(void)
2466 int handle, filenum;
2468 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2470 handle = PRVM_G_FLOAT(OFS_PARM0);
2471 filenum = PRVM_G_FLOAT(OFS_PARM1);
2473 if(handle < 0 || handle >= MAX_VMSEARCHES)
2475 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2478 if(VM_SEARCHLIST[handle] == NULL)
2480 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2483 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2485 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2489 tmp = VM_GetTempString();
2490 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2492 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2499 string chr(float ascii)
2505 VM_SAFEPARMCOUNT(1, VM_chr);
2507 tmp = VM_GetTempString();
2508 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2511 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2514 //=============================================================================
2515 // Draw builtins (client & menu)
2521 float iscachedpic(string pic)
2524 void VM_iscachedpic(void)
2526 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2528 // drawq hasnt such a function, thus always return true
2529 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2536 string precache_pic(string pic)
2539 void VM_precache_pic(void)
2543 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2545 s = PRVM_G_STRING(OFS_PARM0);
2546 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2549 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2551 VM_CheckEmptyString (s);
2553 if(!Draw_CachePic(s))
2554 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2564 void VM_freepic(void)
2568 VM_SAFEPARMCOUNT(1,VM_freepic);
2570 s = PRVM_G_STRING(OFS_PARM0);
2573 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2575 VM_CheckEmptyString (s);
2584 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2587 void VM_drawcharacter(void)
2589 float *pos,*scale,*rgb;
2592 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2594 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2597 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2598 PRVM_G_FLOAT(OFS_RETURN) = -1;
2602 pos = PRVM_G_VECTOR(OFS_PARM0);
2603 scale = PRVM_G_VECTOR(OFS_PARM2);
2604 rgb = PRVM_G_VECTOR(OFS_PARM3);
2605 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2607 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2609 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2610 PRVM_G_FLOAT(OFS_RETURN) = -2;
2614 if(pos[2] || scale[2])
2615 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")));
2617 if(!scale[0] || !scale[1])
2619 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2620 PRVM_G_FLOAT(OFS_RETURN) = -3;
2624 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2625 PRVM_G_FLOAT(OFS_RETURN) = 1;
2632 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2635 void VM_drawstring(void)
2637 float *pos,*scale,*rgb;
2640 VM_SAFEPARMCOUNT(6,VM_drawstring);
2642 string = PRVM_G_STRING(OFS_PARM1);
2645 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2646 PRVM_G_FLOAT(OFS_RETURN) = -1;
2650 VM_CheckEmptyString(string);
2652 pos = PRVM_G_VECTOR(OFS_PARM0);
2653 scale = PRVM_G_VECTOR(OFS_PARM2);
2654 rgb = PRVM_G_VECTOR(OFS_PARM3);
2655 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2657 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2659 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2660 PRVM_G_FLOAT(OFS_RETURN) = -2;
2664 if(!scale[0] || !scale[1])
2666 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2667 PRVM_G_FLOAT(OFS_RETURN) = -3;
2671 if(pos[2] || scale[2])
2672 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")));
2674 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2675 PRVM_G_FLOAT(OFS_RETURN) = 1;
2681 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2684 void VM_drawpic(void)
2687 float *size, *pos, *rgb;
2690 VM_SAFEPARMCOUNT(6,VM_drawpic);
2692 pic = PRVM_G_STRING(OFS_PARM1);
2696 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2697 PRVM_G_FLOAT(OFS_RETURN) = -1;
2701 VM_CheckEmptyString (pic);
2703 // is pic cached ? no function yet for that
2706 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2707 PRVM_G_FLOAT(OFS_RETURN) = -4;
2711 pos = PRVM_G_VECTOR(OFS_PARM0);
2712 size = PRVM_G_VECTOR(OFS_PARM2);
2713 rgb = PRVM_G_VECTOR(OFS_PARM3);
2714 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2716 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2718 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2719 PRVM_G_FLOAT(OFS_RETURN) = -2;
2723 if(pos[2] || size[2])
2724 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")));
2726 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2727 PRVM_G_FLOAT(OFS_RETURN) = 1;
2734 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2737 void VM_drawfill(void)
2739 float *size, *pos, *rgb;
2742 VM_SAFEPARMCOUNT(5,VM_drawfill);
2745 pos = PRVM_G_VECTOR(OFS_PARM0);
2746 size = PRVM_G_VECTOR(OFS_PARM1);
2747 rgb = PRVM_G_VECTOR(OFS_PARM2);
2748 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2750 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2752 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2753 PRVM_G_FLOAT(OFS_RETURN) = -2;
2757 if(pos[2] || size[2])
2758 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")));
2760 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2761 PRVM_G_FLOAT(OFS_RETURN) = 1;
2768 drawsetcliparea(float x, float y, float width, float height)
2771 void VM_drawsetcliparea(void)
2774 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2776 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2777 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2778 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2779 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2781 DrawQ_SetClipArea(x,y,w,h);
2786 VM_drawresetcliparea
2791 void VM_drawresetcliparea(void)
2793 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2795 DrawQ_ResetClipArea();
2802 vector getimagesize(string pic)
2805 void VM_getimagesize(void)
2810 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2812 p = PRVM_G_STRING(OFS_PARM0);
2815 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2817 VM_CheckEmptyString (p);
2819 pic = Draw_CachePic (p);
2821 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2822 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2823 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2826 void VM_Cmd_Init(void)
2828 // only init the stuff for the current prog
2829 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2834 void VM_Cmd_Reset(void)
2836 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2837 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2839 VM_Files_CloseAll();
2842 //============================================================================
2845 char *vm_sv_extensions =
2848 prvm_builtin_t vm_sv_builtins[] = {
2849 0 // to be consistent with the old vm
2852 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2854 void VM_SV_Cmd_Init(void)
2858 void VM_SV_Cmd_Reset(void)
2862 //============================================================================
2865 char *vm_cl_extensions =
2868 prvm_builtin_t vm_cl_builtins[] = {
2869 0 // to be consistent with the old vm
2872 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2874 void VM_CL_Cmd_Init(void)
2878 void VM_CL_Cmd_Reset(void)
2882 //============================================================================
2885 char *vm_m_extensions =
2892 setmousetarget(float target)
2895 void VM_M_setmousetarget(void)
2897 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2899 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2902 in_client_mouse = false;
2905 in_client_mouse = true;
2908 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2916 float getmousetarget
2919 void VM_M_getmousetarget(void)
2921 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2924 PRVM_G_FLOAT(OFS_RETURN) = 2;
2926 PRVM_G_FLOAT(OFS_RETURN) = 1;
2935 setkeydest(float dest)
2938 void VM_M_setkeydest(void)
2940 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2942 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2946 key_dest = key_game;
2950 key_dest = key_menu;
2954 // key_dest = key_message
2957 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2968 void VM_M_getkeydest(void)
2970 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2972 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2976 PRVM_G_FLOAT(OFS_RETURN) = 0;
2979 PRVM_G_FLOAT(OFS_RETURN) = 2;
2983 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2986 PRVM_G_FLOAT(OFS_RETURN) = 3;
2994 callfunction(...,string function_name)
2998 mfunction_t *PRVM_ED_FindFunction (const char *name);
2999 void VM_M_callfunction(void)
3005 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3007 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3010 PRVM_ERROR("VM_M_callfunction: null string !\n");
3012 VM_CheckEmptyString(s);
3014 func = PRVM_ED_FindFunction(s);
3017 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3018 else if (func->first_statement < 0)
3020 // negative statements are built in functions
3021 int builtinnumber = -func->first_statement;
3022 prog->xfunction->builtinsprofile++;
3023 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3024 prog->builtins[builtinnumber]();
3026 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3031 PRVM_ExecuteProgram(func - prog->functions,"");
3040 float isfunction(string function_name)
3043 mfunction_t *PRVM_ED_FindFunction (const char *name);
3044 void VM_M_isfunction(void)
3049 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3051 s = PRVM_G_STRING(OFS_PARM0);
3054 PRVM_ERROR("VM_M_isfunction: null string !\n");
3056 VM_CheckEmptyString(s);
3058 func = PRVM_ED_FindFunction(s);
3061 PRVM_G_FLOAT(OFS_RETURN) = false;
3063 PRVM_G_FLOAT(OFS_RETURN) = true;
3070 writetofile(float fhandle, entity ent)
3073 void VM_M_writetofile(void)
3078 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3080 filenum = PRVM_G_FLOAT(OFS_PARM0);
3081 if (filenum < 0 || filenum >= MAX_VMFILES)
3083 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3086 if (VM_FILES[filenum] == NULL)
3088 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3092 ent = PRVM_G_EDICT(OFS_PARM1);
3095 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3099 PRVM_ED_Write (VM_FILES[filenum], ent);
3106 vector getresolution(float number)
3109 extern unsigned short video_resolutions[][2];
3110 void VM_M_getresolution(void)
3113 VM_SAFEPARMCOUNT(1, VM_getresolution);
3115 nr = PRVM_G_FLOAT(OFS_PARM0);
3118 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3119 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3120 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3127 string keynumtostring(float keynum)
3130 void VM_M_keynumtostring(void)
3134 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3136 keynum = PRVM_G_FLOAT(OFS_PARM0);
3138 tmp = VM_GetTempString();
3140 strcpy(tmp, Key_KeynumToString(keynum));
3142 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3147 VM_M_findkeysforcommand
3149 string findkeysforcommand(string command)
3151 the returned string is an altstring
3154 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3156 void M_FindKeysForCommand(char *command, int *keys);
3157 void VM_M_findkeysforcommand(void)
3163 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3165 cmd = PRVM_G_STRING(OFS_PARM0);
3167 VM_CheckEmptyString(cmd);
3169 (ret = VM_GetTempString())[0] = 0;
3171 M_FindKeysForCommand(cmd, keys);
3173 for(i = 0; i < NUMKEYS; i++)
3174 ret = strcat(ret, va(" \'%i\'", keys[i]));
3176 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3181 VM_M_gethostcachecount
3183 float gethostcachevalue(float type)
3194 void VM_M_gethostcachevalue( void )
3197 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3199 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3201 type = PRVM_G_FLOAT( OFS_PARM0 );
3202 if( type < 0 || type > 4 )
3203 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3207 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3210 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3213 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3216 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3219 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3226 VM_M_gethostcachestring
3228 string gethostcachestring(float type, float hostnr)
3236 void VM_M_gethostcachestring(void)
3241 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3243 PRVM_G_INT(OFS_RETURN) = 0;
3245 type = PRVM_G_FLOAT(OFS_PARM0);
3247 if(type < 0 || type > 2)
3249 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3253 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3255 if(hostnr < 0 || hostnr >= hostCacheCount)
3257 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3262 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3263 else if( type == 1 )
3264 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3266 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3269 prvm_builtin_t vm_m_builtins[] = {
3270 0, // to be consistent with the old vm
3271 // common builtings (mostly)
3348 VM_search_getfilename, // 77
3365 VM_WriteEntity, // 408
3381 VM_drawresetcliparea,
3382 VM_getimagesize,// 460
3391 VM_M_setmousetarget,
3392 VM_M_getmousetarget,
3397 VM_M_keynumtostring,
3398 VM_M_findkeysforcommand,// 610
3399 VM_M_gethostcachevalue,
3400 VM_M_gethostcachestring,
3401 VM_M_parseentitydata // 613
3404 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3406 void VM_M_Cmd_Init(void)
3411 void VM_M_Cmd_Reset(void)