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 if (!client->netconnection)
397 VM_VarString(1, string, sizeof(string));
398 MSG_WriteChar(&client->message,svc_print);
399 MSG_WriteString(&client->message, string);
406 single print to the screen
408 centerprint(clientent, value)
411 void VM_centerprint (void)
413 char string[VM_STRINGTEMP_LENGTH];
415 VM_VarString(0, string, sizeof(string));
416 SCR_CenterPrint(string);
423 vector normalize(vector)
426 void VM_normalize (void)
432 VM_SAFEPARMCOUNT(1,VM_normalize);
434 value1 = PRVM_G_VECTOR(OFS_PARM0);
436 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
440 newvalue[0] = newvalue[1] = newvalue[2] = 0;
444 newvalue[0] = value1[0] * new;
445 newvalue[1] = value1[1] * new;
446 newvalue[2] = value1[2] * new;
449 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
464 VM_SAFEPARMCOUNT(1,VM_vlen);
466 value1 = PRVM_G_VECTOR(OFS_PARM0);
468 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
471 PRVM_G_FLOAT(OFS_RETURN) = new;
478 float vectoyaw(vector)
481 void VM_vectoyaw (void)
486 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
488 value1 = PRVM_G_VECTOR(OFS_PARM0);
490 if (value1[1] == 0 && value1[0] == 0)
494 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
499 PRVM_G_FLOAT(OFS_RETURN) = yaw;
507 vector vectoangles(vector)
510 void VM_vectoangles (void)
516 VM_SAFEPARMCOUNT(1,VM_vectoangles);
518 value1 = PRVM_G_VECTOR(OFS_PARM0);
520 if (value1[1] == 0 && value1[0] == 0)
530 // LordHavoc: optimized a bit
533 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
537 else if (value1[1] > 0)
542 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
543 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
548 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
549 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
550 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
557 Returns a number from 0<= num < 1
562 void VM_random (void)
566 VM_SAFEPARMCOUNT(0,VM_random);
568 num = (rand ()&0x7fff) / ((float)0x7fff);
570 PRVM_G_FLOAT(OFS_RETURN) = num;
577 Each entity can have eight independant sound sources, like voice,
580 Channel 0 is an auto-allocate channel, the others override anything
581 already running on that entity/channel pair.
583 An attenuation of 0 will play full volume everywhere in the level.
584 Larger attenuations will drop off.
597 entity = G_EDICT(OFS_PARM0);
598 channel = G_FLOAT(OFS_PARM1);
599 sample = G_STRING(OFS_PARM2);
600 volume = G_FLOAT(OFS_PARM3) * 255;
601 attenuation = G_FLOAT(OFS_PARM4);
603 if (volume < 0 || volume > 255)
604 Host_Error ("SV_StartSound: volume = %i", volume);
606 if (attenuation < 0 || attenuation > 4)
607 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
609 if (channel < 0 || channel > 7)
610 Host_Error ("SV_StartSound: channel = %i", channel);
612 SV_StartSound (entity, channel, sample, volume, attenuation);
620 localsound(string sample)
623 void VM_localsound(void)
627 VM_SAFEPARMCOUNT(1,VM_localsound);
629 s = PRVM_G_STRING(OFS_PARM0);
631 if(!S_LocalSound (s))
633 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
634 PRVM_G_FLOAT(OFS_RETURN) = -4;
638 PRVM_G_FLOAT(OFS_RETURN) = 1;
650 PRVM_ERROR ("%s: break statement", PRVM_NAME);
653 //============================================================================
659 Sends text over to the client's execution buffer
661 [localcmd (string) or]
665 void VM_localcmd (void)
667 VM_SAFEPARMCOUNT(1,VM_localcmd);
669 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
681 VM_SAFEPARMCOUNT(1,VM_cvar);
683 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
690 const string str_cvar (string)
693 void VM_str_cvar(void)
696 const char *cvar_string;
697 VM_SAFEPARMCOUNT(1,VM_str_cvar);
699 name = PRVM_G_STRING(OFS_PARM0);
702 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
704 VM_CheckEmptyString(name);
706 out = VM_GetTempString();
708 cvar_string = Cvar_VariableString(name);
710 strcpy(out, cvar_string);
712 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
719 void cvar_set (string,string)
722 void VM_cvar_set (void)
724 VM_SAFEPARMCOUNT(2,VM_cvar_set);
726 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
736 void VM_dprint (void)
738 char string[VM_STRINGTEMP_LENGTH];
739 if (developer.integer)
741 VM_VarString(0, string, sizeof(string));
742 Con_Printf("%s: %s", PRVM_NAME, string);
759 VM_SAFEPARMCOUNT(1, VM_ftos);
761 v = PRVM_G_FLOAT(OFS_PARM0);
763 s = VM_GetTempString();
764 if ((float)((int)v) == v)
765 sprintf(s, "%i", (int)v);
768 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
783 VM_SAFEPARMCOUNT(1,VM_fabs);
785 v = PRVM_G_FLOAT(OFS_PARM0);
786 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
801 VM_SAFEPARMCOUNT(1,VM_vtos);
803 s = VM_GetTempString();
804 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]);
805 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
820 VM_SAFEPARMCOUNT(1, VM_etos);
822 s = VM_GetTempString();
823 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
824 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
831 float stof(...[string])
836 char string[VM_STRINGTEMP_LENGTH];
837 VM_VarString(0, string, sizeof(string));
838 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
842 ========================
846 ========================
850 VM_SAFEPARMCOUNT(1, VM_itof);
851 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
855 ========================
859 ========================
864 VM_SAFEPARMCOUNT(1, VM_ftoi);
866 ent = PRVM_G_FLOAT(OFS_PARM0);
867 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
868 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
870 PRVM_G_INT(OFS_RETURN) = ent;
884 prog->xfunction->builtinsprofile += 20;
885 ed = PRVM_ED_Alloc();
897 void VM_remove (void)
900 prog->xfunction->builtinsprofile += 20;
902 VM_SAFEPARMCOUNT(1, VM_remove);
904 ed = PRVM_G_EDICT(OFS_PARM0);
905 // if (ed == prog->edicts)
906 // PRVM_ERROR ("remove: tried to remove world\n");
907 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
908 // Host_Error("remove: tried to remove a client\n");
916 entity find(entity start, .string field, string match)
927 VM_SAFEPARMCOUNT(3,VM_find);
929 e = PRVM_G_EDICTNUM(OFS_PARM0);
930 f = PRVM_G_INT(OFS_PARM1);
931 s = PRVM_G_STRING(OFS_PARM2);
935 // return reserved edict 0 (could be used for whatever the prog wants)
936 VM_RETURN_EDICT(prog->edicts);
940 for (e++ ; e < prog->num_edicts ; e++)
942 prog->xfunction->builtinsprofile++;
943 ed = PRVM_EDICT_NUM(e);
946 t = PRVM_E_STRING(ed,f);
956 VM_RETURN_EDICT(prog->edicts);
963 entity findfloat(entity start, .float field, float match)
964 entity findentity(entity start, .entity field, entity match)
967 // LordHavoc: added this for searching float, int, and entity reference fields
968 void VM_findfloat (void)
975 VM_SAFEPARMCOUNT(3,VM_findfloat);
977 e = PRVM_G_EDICTNUM(OFS_PARM0);
978 f = PRVM_G_INT(OFS_PARM1);
979 s = PRVM_G_FLOAT(OFS_PARM2);
981 for (e++ ; e < prog->num_edicts ; e++)
983 prog->xfunction->builtinsprofile++;
984 ed = PRVM_EDICT_NUM(e);
987 if (PRVM_E_FLOAT(ed,f) == s)
994 VM_RETURN_EDICT(prog->edicts);
1001 entity findchain(.string field, string match)
1004 int PRVM_ED_FindFieldOffset(const char *field);
1005 // chained search for strings in entity fields
1006 // entity(.string field, string match) findchain = #402;
1007 void VM_findchain (void)
1013 prvm_edict_t *ent, *chain;
1015 VM_SAFEPARMCOUNT(2,VM_findchain);
1017 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1018 if(!prog->flag & PRVM_FE_CHAIN)
1019 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1021 chain_of = PRVM_ED_FindFieldOffset ("chain");
1023 chain = prog->edicts;
1025 f = PRVM_G_INT(OFS_PARM0);
1026 s = PRVM_G_STRING(OFS_PARM1);
1029 VM_RETURN_EDICT(prog->edicts);
1033 ent = PRVM_NEXT_EDICT(prog->edicts);
1034 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1036 prog->xfunction->builtinsprofile++;
1039 t = PRVM_E_STRING(ent,f);
1045 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1049 VM_RETURN_EDICT(chain);
1056 entity findchainfloat(.string field, float match)
1057 entity findchainentity(.string field, entity match)
1060 // LordHavoc: chained search for float, int, and entity reference fields
1061 // entity(.string field, float match) findchainfloat = #403;
1062 void VM_findchainfloat (void)
1068 prvm_edict_t *ent, *chain;
1070 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1072 if(!prog->flag & PRVM_FE_CHAIN)
1073 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1075 chain_of = PRVM_ED_FindFieldOffset ("chain");
1077 chain = (prvm_edict_t *)prog->edicts;
1079 f = PRVM_G_INT(OFS_PARM0);
1080 s = PRVM_G_FLOAT(OFS_PARM1);
1082 ent = PRVM_NEXT_EDICT(prog->edicts);
1083 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1085 prog->xfunction->builtinsprofile++;
1088 if (E_FLOAT(ent,f) != s)
1091 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1095 VM_RETURN_EDICT(chain);
1102 string precache_file(string)
1105 void VM_precache_file (void)
1106 { // precache_file is only used to copy files with qcc, it does nothing
1107 VM_SAFEPARMCOUNT(1,VM_precache_file);
1109 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1116 used instead of the other VM_precache_* functions in the builtin list
1120 void VM_precache_error (void)
1122 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1129 string precache_sound (string sample)
1132 void VM_precache_sound (void)
1136 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1138 s = PRVM_G_STRING(OFS_PARM0);
1139 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1140 VM_CheckEmptyString (s);
1142 if(!S_PrecacheSound (s,true, true))
1143 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1153 void VM_coredump (void)
1155 VM_SAFEPARMCOUNT(0,VM_coredump);
1157 Cbuf_AddText("prvm_edicts ");
1158 Cbuf_AddText(PRVM_NAME);
1169 void PRVM_StackTrace(void);
1170 void VM_stackdump (void)
1172 VM_SAFEPARMCOUNT(0, VM_stackdump);
1187 VM_SAFEPARMCOUNT(0, VM_crash);
1189 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1199 void VM_traceon (void)
1201 VM_SAFEPARMCOUNT(0,VM_traceon);
1213 void VM_traceoff (void)
1215 VM_SAFEPARMCOUNT(0,VM_traceoff);
1217 prog->trace = false;
1227 void VM_eprint (void)
1229 VM_SAFEPARMCOUNT(1,VM_eprint);
1231 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1245 VM_SAFEPARMCOUNT(1,VM_rint);
1247 f = PRVM_G_FLOAT(OFS_PARM0);
1249 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1251 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1261 void VM_floor (void)
1263 VM_SAFEPARMCOUNT(1,VM_floor);
1265 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1277 VM_SAFEPARMCOUNT(1,VM_ceil);
1279 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1287 entity nextent(entity)
1290 void VM_nextent (void)
1295 i = PRVM_G_EDICTNUM(OFS_PARM0);
1298 prog->xfunction->builtinsprofile++;
1300 if (i == prog->num_edicts)
1302 VM_RETURN_EDICT(prog->edicts);
1305 ent = PRVM_EDICT_NUM(i);
1306 if (!ent->p.e->free)
1308 VM_RETURN_EDICT(ent);
1315 ===============================================================================
1318 used only for client and menu
1319 severs uses VM_SV_...
1321 Write*(* data, float type, float to)
1323 ===============================================================================
1326 #define MSG_BROADCAST 0 // unreliable to all
1327 #define MSG_ONE 1 // reliable to one (msg_entity)
1328 #define MSG_ALL 2 // reliable to all
1329 #define MSG_INIT 3 // write to the init string
1331 sizebuf_t *VM_WriteDest (void)
1337 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1339 dest = G_FLOAT(OFS_PARM1);
1343 return &sv.datagram;
1346 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1347 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1348 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1350 return &svs.clients[destclient].message;
1353 return &sv.reliable_datagram;
1359 PRVM_ERROR ("WriteDest: bad destination");
1366 void VM_WriteByte (void)
1368 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1371 void VM_WriteChar (void)
1373 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1376 void VM_WriteShort (void)
1378 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1381 void VM_WriteLong (void)
1383 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1386 void VM_WriteAngle (void)
1388 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1391 void VM_WriteCoord (void)
1393 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1396 void VM_WriteString (void)
1398 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1401 void VM_WriteEntity (void)
1403 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1406 //=============================================================================
1413 changelevel(string map)
1416 void VM_changelevel (void)
1420 VM_SAFEPARMCOUNT(1, VM_changelevel);
1424 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1428 // make sure we don't issue two changelevels
1429 if (svs.changelevel_issued)
1431 svs.changelevel_issued = true;
1433 s = G_STRING(OFS_PARM0);
1434 Cbuf_AddText (va("changelevel %s\n",s));
1446 VM_SAFEPARMCOUNT(1,VM_sin);
1447 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1458 VM_SAFEPARMCOUNT(1,VM_cos);
1459 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1471 VM_SAFEPARMCOUNT(1,VM_sqrt);
1472 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1479 Returns a vector of length < 1 and > 0
1484 void VM_randomvec (void)
1489 VM_SAFEPARMCOUNT(0, VM_randomvec);
1494 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1495 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1496 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1498 while (DotProduct(temp, temp) >= 1);
1499 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1502 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1503 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1504 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1505 // length returned always > 0
1506 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1507 VectorScale(temp,length, temp);*/
1508 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1511 //=============================================================================
1517 float registercvar (string name, string value, float flags)
1520 void VM_registercvar (void)
1525 VM_SAFEPARMCOUNT(3,VM_registercvar);
1527 name = PRVM_G_STRING(OFS_PARM0);
1528 value = PRVM_G_STRING(OFS_PARM1);
1529 flags = PRVM_G_FLOAT(OFS_PARM2);
1530 PRVM_G_FLOAT(OFS_RETURN) = 0;
1532 if(flags > CVAR_MAXFLAGSVAL)
1535 // first check to see if it has already been defined
1536 if (Cvar_FindVar (name))
1539 // check for overlap with a command
1540 if (Cmd_Exists (name))
1542 Con_Printf("VM_registercvar: %s is a command\n", name);
1546 Cvar_Get(name, value, flags);
1548 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1555 returns the minimum of two supplied floats
1557 float min(float a, float b, ...[float])
1562 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1563 if (prog->argc == 2)
1564 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1565 else if (prog->argc >= 3)
1568 float f = PRVM_G_FLOAT(OFS_PARM0);
1569 for (i = 1;i < prog->argc;i++)
1570 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1571 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1572 PRVM_G_FLOAT(OFS_RETURN) = f;
1575 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1582 returns the maximum of two supplied floats
1584 float max(float a, float b, ...[float])
1589 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1590 if (prog->argc == 2)
1591 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1592 else if (prog->argc >= 3)
1595 float f = PRVM_G_FLOAT(OFS_PARM0);
1596 for (i = 1;i < prog->argc;i++)
1597 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1598 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1599 G_FLOAT(OFS_RETURN) = f;
1602 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1609 returns number bounded by supplied range
1611 float bound(float min, float value, float max)
1614 void VM_bound (void)
1616 VM_SAFEPARMCOUNT(3,VM_bound);
1617 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1624 returns a raised to power b
1626 float pow(float a, float b)
1631 VM_SAFEPARMCOUNT(2,VM_pow);
1632 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1639 copies data from one entity to another
1641 copyentity(entity src, entity dst)
1644 void VM_copyentity (void)
1646 prvm_edict_t *in, *out;
1647 VM_SAFEPARMCOUNT(2,VM_copyentity);
1648 in = PRVM_G_EDICT(OFS_PARM0);
1649 out = PRVM_G_EDICT(OFS_PARM1);
1650 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1657 sets the color of a client and broadcasts the update to all connected clients
1659 setcolor(clientent, value)
1662 /*void PF_setcolor (void)
1668 entnum = G_EDICTNUM(OFS_PARM0);
1669 i = G_FLOAT(OFS_PARM1);
1671 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1673 Con_Print("tried to setcolor a non-client\n");
1677 client = svs.clients + entnum-1;
1678 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1681 client->old_colors = i;
1682 client->edict->v->team = (i & 15) + 1;
1684 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1685 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1686 MSG_WriteByte (&sv.reliable_datagram, i);
1689 void VM_Files_Init(void)
1691 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1694 void VM_Files_CloseAll(void)
1697 for (i = 0;i < MAX_VMFILES;i++)
1700 FS_Close(VM_FILES[i]);
1701 //VM_FILES[i] = NULL;
1703 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1710 float fopen(string filename, float mode)
1713 // float(string filename, float mode) fopen = #110;
1714 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1715 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1719 char *modestring, *filename;
1721 VM_SAFEPARMCOUNT(2,VM_fopen);
1723 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1724 if (VM_FILES[filenum] == NULL)
1726 if (filenum >= MAX_VMFILES)
1728 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1729 PRVM_G_FLOAT(OFS_RETURN) = -2;
1732 mode = PRVM_G_FLOAT(OFS_PARM1);
1735 case 0: // FILE_READ
1738 case 1: // FILE_APPEND
1741 case 2: // FILE_WRITE
1745 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1746 PRVM_G_FLOAT(OFS_RETURN) = -3;
1749 filename = PRVM_G_STRING(OFS_PARM0);
1750 // .. is parent directory on many platforms
1751 // / is parent directory on Amiga
1752 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1753 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1754 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1756 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1757 PRVM_G_FLOAT(OFS_RETURN) = -4;
1760 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1761 if (VM_FILES[filenum] == NULL && mode == 0)
1762 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1764 if (VM_FILES[filenum] == NULL)
1765 PRVM_G_FLOAT(OFS_RETURN) = -1;
1767 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1774 fclose(float fhandle)
1777 //void(float fhandle) fclose = #111; // closes a file
1778 void VM_fclose(void)
1782 VM_SAFEPARMCOUNT(1,VM_fclose);
1784 filenum = PRVM_G_FLOAT(OFS_PARM0);
1785 if (filenum < 0 || filenum >= MAX_VMFILES)
1787 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1790 if (VM_FILES[filenum] == NULL)
1792 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1795 FS_Close(VM_FILES[filenum]);
1796 VM_FILES[filenum] = NULL;
1803 string fgets(float fhandle)
1806 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1810 static char string[VM_STRINGTEMP_LENGTH];
1813 VM_SAFEPARMCOUNT(1,VM_fgets);
1815 filenum = PRVM_G_FLOAT(OFS_PARM0);
1816 if (filenum < 0 || filenum >= MAX_VMFILES)
1818 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1821 if (VM_FILES[filenum] == NULL)
1823 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1829 c = FS_Getc(VM_FILES[filenum]);
1830 if (c == '\r' || c == '\n' || c < 0)
1832 if (end < VM_STRINGTEMP_LENGTH - 1)
1836 // remove \n following \r
1838 c = FS_Getc(VM_FILES[filenum]);
1839 if (developer.integer)
1840 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1842 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1844 PRVM_G_INT(OFS_RETURN) = 0;
1851 fputs(float fhandle, string s)
1854 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1858 char string[VM_STRINGTEMP_LENGTH];
1861 VM_SAFEPARMCOUNT(2,VM_fputs);
1863 filenum = PRVM_G_FLOAT(OFS_PARM0);
1864 if (filenum < 0 || filenum >= MAX_VMFILES)
1866 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1869 if (VM_FILES[filenum] == NULL)
1871 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1874 VM_VarString(1, string, sizeof(string));
1875 if ((stringlength = strlen(string)))
1876 FS_Write(VM_FILES[filenum], string, stringlength);
1877 if (developer.integer)
1878 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1885 float strlen(string s)
1888 //float(string s) strlen = #114; // returns how many characters are in a string
1889 void VM_strlen(void)
1893 VM_SAFEPARMCOUNT(1,VM_strlen);
1895 s = PRVM_G_STRING(OFS_PARM0);
1897 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1899 PRVM_G_FLOAT(OFS_RETURN) = 0;
1906 string strcat(string,string,...[string])
1909 //string(string s1, string s2) strcat = #115;
1910 // concatenates two strings (for example "abc", "def" would return "abcdef")
1911 // and returns as a tempstring
1912 void VM_strcat(void)
1917 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1919 s = VM_GetTempString();
1920 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1921 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1928 string substring(string s, float start, float length)
1931 // string(string s, float start, float length) substring = #116;
1932 // returns a section of a string as a tempstring
1933 void VM_substring(void)
1935 int i, start, length;
1938 VM_SAFEPARMCOUNT(3,VM_substring);
1940 string = VM_GetTempString();
1941 s = PRVM_G_STRING(OFS_PARM0);
1942 start = PRVM_G_FLOAT(OFS_PARM1);
1943 length = PRVM_G_FLOAT(OFS_PARM2);
1946 for (i = 0;i < start && *s;i++, s++);
1947 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1950 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1957 vector stov(string s)
1960 //vector(string s) stov = #117; // returns vector value from a string
1963 char string[VM_STRINGTEMP_LENGTH];
1965 VM_SAFEPARMCOUNT(1,VM_stov);
1967 VM_VarString(0, string, sizeof(string));
1968 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1975 string strzone(string s)
1978 //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)
1979 void VM_strzone(void)
1983 VM_SAFEPARMCOUNT(1,VM_strzone);
1985 in = PRVM_G_STRING(OFS_PARM0);
1986 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1988 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1998 //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!!!)
1999 void VM_strunzone(void)
2002 VM_SAFEPARMCOUNT(1,VM_strunzone);
2004 str = PRVM_G_STRING(OFS_PARM0);
2005 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2006 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2013 VM_command (used by client and menu)
2015 clientcommand(float client, string s) (for client and menu)
2018 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2019 //this function originally written by KrimZon, made shorter by LordHavoc
2020 void VM_clcommand (void)
2022 client_t *temp_client;
2025 VM_SAFEPARMCOUNT(2,VM_clcommand);
2027 i = PRVM_G_FLOAT(OFS_PARM0);
2028 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2030 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2034 temp_client = host_client;
2035 host_client = svs.clients + i;
2036 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2037 host_client = temp_client;
2045 float tokenize(string s)
2048 //float(string s) tokenize = #441;
2049 // takes apart a string into individal words (access them with argv), returns how many
2050 // this function originally written by KrimZon, made shorter by LordHavoc
2051 static char **tokens = NULL;
2052 static int max_tokens, num_tokens = 0;
2053 void VM_tokenize (void)
2058 VM_SAFEPARMCOUNT(1,VM_tokenize);
2060 str = PRVM_G_STRING(OFS_PARM0);
2065 for (i=0;i<num_tokens;i++)
2071 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2072 max_tokens = strlen(str);
2074 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2076 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2077 strcpy(tokens[num_tokens], com_token);
2080 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2087 string argv(float n)
2090 //string(float n) argv = #442;
2091 // returns a word from the tokenized string (returns nothing for an invalid index)
2092 // this function originally written by KrimZon, made shorter by LordHavoc
2097 VM_SAFEPARMCOUNT(1,VM_argv);
2099 token_num = PRVM_G_FLOAT(OFS_PARM0);
2100 if (token_num >= 0 && token_num < num_tokens)
2101 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2103 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2107 //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)
2108 void PF_setattachment (void)
2110 edict_t *e = G_EDICT(OFS_PARM0);
2111 edict_t *tagentity = G_EDICT(OFS_PARM1);
2112 char *tagname = G_STRING(OFS_PARM2);
2117 if (tagentity == NULL)
2118 tagentity = sv.edicts;
2120 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2122 v->edict = EDICT_TO_PROG(tagentity);
2124 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2127 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2129 modelindex = (int)tagentity->v->modelindex;
2130 if (modelindex >= 0 && modelindex < MAX_MODELS)
2132 model = sv.models[modelindex];
2133 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2134 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2135 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2137 // FIXME: use a model function to get tag info (need to handle skeletal)
2138 if (v->_float == 0 && model->alias.aliasnum_tags)
2139 for (i = 0;i < model->alias.aliasnum_tags;i++)
2140 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2143 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);
2146 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));
2157 void VM_isserver(void)
2159 VM_SAFEPARMCOUNT(0,VM_serverstate);
2161 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2171 void VM_clientcount(void)
2173 VM_SAFEPARMCOUNT(0,VM_clientcount);
2175 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2185 void VM_clientstate(void)
2187 VM_SAFEPARMCOUNT(0,VM_clientstate);
2189 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2196 float getostype(void)
2198 */ // not used at the moment -> not included in the common list
2199 void VM_getostype(void)
2201 VM_SAFEPARMCOUNT(0,VM_getostype);
2206 OS_MAC - not supported
2210 PRVM_G_FLOAT(OFS_RETURN) = 0;
2212 PRVM_G_FLOAT(OFS_RETURN) = 2;
2214 PRVM_G_FLOAT(OFS_RETURN) = 1;
2222 vector getmousepos()
2225 void VM_getmousepos(void)
2228 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2230 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2231 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2232 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2242 void VM_gettime(void)
2244 VM_SAFEPARMCOUNT(0,VM_gettime);
2246 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2253 loadfromdata(string data)
2256 void VM_loadfromdata(void)
2258 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2260 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2264 ========================
2265 VM_M_parseentitydata
2267 parseentitydata(entity ent, string data)
2268 ========================
2270 void VM_M_parseentitydata(void)
2275 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2277 // get edict and test it
2278 ent = PRVM_G_EDICT(OFS_PARM0);
2280 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2282 data = PRVM_G_STRING(OFS_PARM1);
2284 // parse the opening brace
2285 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2286 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2288 PRVM_ED_ParseEdict (data, ent);
2295 loadfromfile(string file)
2298 void VM_loadfromfile(void)
2303 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2305 filename = PRVM_G_STRING(OFS_PARM0);
2306 // .. is parent directory on many platforms
2307 // / is parent directory on Amiga
2308 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2309 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2310 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2312 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2313 PRVM_G_FLOAT(OFS_RETURN) = -4;
2317 // not conform with VM_fopen
2318 data = FS_LoadFile(filename, tempmempool, false);
2320 PRVM_G_FLOAT(OFS_RETURN) = -1;
2322 PRVM_ED_LoadFromFile(data);
2333 float mod(float val, float m)
2336 void VM_modulo(void)
2339 VM_SAFEPARMCOUNT(2,VM_module);
2341 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2342 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2344 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2347 void VM_Search_Init(void)
2349 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2352 void VM_Search_Reset(void)
2355 // reset the fssearch list
2356 for(i = 0; i < MAX_VMSEARCHES; i++)
2357 if(VM_SEARCHLIST[i])
2358 FS_FreeSearch(VM_SEARCHLIST[i]);
2359 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2366 float search_begin(string pattern, float caseinsensitive, float quiet)
2369 void VM_search_begin(void)
2373 int caseinsens, quiet;
2375 VM_SAFEPARMCOUNT(3, VM_search_begin);
2377 pattern = PRVM_G_STRING(OFS_PARM0);
2379 VM_CheckEmptyString(pattern);
2381 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2382 quiet = PRVM_G_FLOAT(OFS_PARM2);
2384 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2385 if(!VM_SEARCHLIST[handle])
2388 if(handle >= MAX_VMSEARCHES)
2390 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2391 PRVM_G_FLOAT(OFS_RETURN) = -2;
2395 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2396 PRVM_G_FLOAT(OFS_RETURN) = -1;
2398 PRVM_G_FLOAT(OFS_RETURN) = handle;
2405 void search_end(float handle)
2408 void VM_search_end(void)
2411 VM_SAFEPARMCOUNT(1, VM_search_end);
2413 handle = PRVM_G_FLOAT(OFS_PARM0);
2415 if(handle < 0 || handle >= MAX_VMSEARCHES)
2417 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2420 if(VM_SEARCHLIST[handle] == NULL)
2422 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2426 FS_FreeSearch(VM_SEARCHLIST[handle]);
2427 VM_SEARCHLIST[handle] = NULL;
2434 float search_getsize(float handle)
2437 void VM_search_getsize(void)
2440 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2442 handle = PRVM_G_FLOAT(OFS_PARM0);
2444 if(handle < 0 || handle >= MAX_VMSEARCHES)
2446 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2449 if(VM_SEARCHLIST[handle] == NULL)
2451 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2455 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2460 VM_search_getfilename
2462 string search_getfilename(float handle, float num)
2465 void VM_search_getfilename(void)
2467 int handle, filenum;
2469 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2471 handle = PRVM_G_FLOAT(OFS_PARM0);
2472 filenum = PRVM_G_FLOAT(OFS_PARM1);
2474 if(handle < 0 || handle >= MAX_VMSEARCHES)
2476 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2479 if(VM_SEARCHLIST[handle] == NULL)
2481 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2484 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2486 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2490 tmp = VM_GetTempString();
2491 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2493 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2500 string chr(float ascii)
2506 VM_SAFEPARMCOUNT(1, VM_chr);
2508 tmp = VM_GetTempString();
2509 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2512 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2515 //=============================================================================
2516 // Draw builtins (client & menu)
2522 float iscachedpic(string pic)
2525 void VM_iscachedpic(void)
2527 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2529 // drawq hasnt such a function, thus always return true
2530 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2537 string precache_pic(string pic)
2540 void VM_precache_pic(void)
2544 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2546 s = PRVM_G_STRING(OFS_PARM0);
2547 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2550 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2552 VM_CheckEmptyString (s);
2554 if(!Draw_CachePic(s))
2555 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2565 void VM_freepic(void)
2569 VM_SAFEPARMCOUNT(1,VM_freepic);
2571 s = PRVM_G_STRING(OFS_PARM0);
2574 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2576 VM_CheckEmptyString (s);
2585 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2588 void VM_drawcharacter(void)
2590 float *pos,*scale,*rgb;
2593 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2595 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2598 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2599 PRVM_G_FLOAT(OFS_RETURN) = -1;
2603 pos = PRVM_G_VECTOR(OFS_PARM0);
2604 scale = PRVM_G_VECTOR(OFS_PARM2);
2605 rgb = PRVM_G_VECTOR(OFS_PARM3);
2606 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2608 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2610 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2611 PRVM_G_FLOAT(OFS_RETURN) = -2;
2615 if(pos[2] || scale[2])
2616 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")));
2618 if(!scale[0] || !scale[1])
2620 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2621 PRVM_G_FLOAT(OFS_RETURN) = -3;
2625 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2626 PRVM_G_FLOAT(OFS_RETURN) = 1;
2633 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2636 void VM_drawstring(void)
2638 float *pos,*scale,*rgb;
2641 VM_SAFEPARMCOUNT(6,VM_drawstring);
2643 string = PRVM_G_STRING(OFS_PARM1);
2646 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2647 PRVM_G_FLOAT(OFS_RETURN) = -1;
2651 VM_CheckEmptyString(string);
2653 pos = PRVM_G_VECTOR(OFS_PARM0);
2654 scale = PRVM_G_VECTOR(OFS_PARM2);
2655 rgb = PRVM_G_VECTOR(OFS_PARM3);
2656 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2658 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2660 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2661 PRVM_G_FLOAT(OFS_RETURN) = -2;
2665 if(!scale[0] || !scale[1])
2667 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2668 PRVM_G_FLOAT(OFS_RETURN) = -3;
2672 if(pos[2] || scale[2])
2673 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")));
2675 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2676 PRVM_G_FLOAT(OFS_RETURN) = 1;
2682 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2685 void VM_drawpic(void)
2688 float *size, *pos, *rgb;
2691 VM_SAFEPARMCOUNT(6,VM_drawpic);
2693 pic = PRVM_G_STRING(OFS_PARM1);
2697 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2698 PRVM_G_FLOAT(OFS_RETURN) = -1;
2702 VM_CheckEmptyString (pic);
2704 // is pic cached ? no function yet for that
2707 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2708 PRVM_G_FLOAT(OFS_RETURN) = -4;
2712 pos = PRVM_G_VECTOR(OFS_PARM0);
2713 size = PRVM_G_VECTOR(OFS_PARM2);
2714 rgb = PRVM_G_VECTOR(OFS_PARM3);
2715 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2717 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2719 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2720 PRVM_G_FLOAT(OFS_RETURN) = -2;
2724 if(pos[2] || size[2])
2725 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")));
2727 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2728 PRVM_G_FLOAT(OFS_RETURN) = 1;
2735 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2738 void VM_drawfill(void)
2740 float *size, *pos, *rgb;
2743 VM_SAFEPARMCOUNT(5,VM_drawfill);
2746 pos = PRVM_G_VECTOR(OFS_PARM0);
2747 size = PRVM_G_VECTOR(OFS_PARM1);
2748 rgb = PRVM_G_VECTOR(OFS_PARM2);
2749 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2751 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2753 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2754 PRVM_G_FLOAT(OFS_RETURN) = -2;
2758 if(pos[2] || size[2])
2759 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")));
2761 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2762 PRVM_G_FLOAT(OFS_RETURN) = 1;
2769 drawsetcliparea(float x, float y, float width, float height)
2772 void VM_drawsetcliparea(void)
2775 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2777 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2778 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2779 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2780 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2782 DrawQ_SetClipArea(x,y,w,h);
2787 VM_drawresetcliparea
2792 void VM_drawresetcliparea(void)
2794 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2796 DrawQ_ResetClipArea();
2803 vector getimagesize(string pic)
2806 void VM_getimagesize(void)
2811 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2813 p = PRVM_G_STRING(OFS_PARM0);
2816 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2818 VM_CheckEmptyString (p);
2820 pic = Draw_CachePic (p);
2822 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2823 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2824 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2827 void VM_Cmd_Init(void)
2829 // only init the stuff for the current prog
2830 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2835 void VM_Cmd_Reset(void)
2837 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2838 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2840 VM_Files_CloseAll();
2843 //============================================================================
2846 char *vm_sv_extensions =
2849 prvm_builtin_t vm_sv_builtins[] = {
2850 0 // to be consistent with the old vm
2853 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2855 void VM_SV_Cmd_Init(void)
2859 void VM_SV_Cmd_Reset(void)
2863 //============================================================================
2866 char *vm_cl_extensions =
2869 prvm_builtin_t vm_cl_builtins[] = {
2870 0 // to be consistent with the old vm
2873 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2875 void VM_CL_Cmd_Init(void)
2879 void VM_CL_Cmd_Reset(void)
2883 //============================================================================
2886 char *vm_m_extensions =
2893 setmousetarget(float target)
2896 void VM_M_setmousetarget(void)
2898 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2900 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2903 in_client_mouse = false;
2906 in_client_mouse = true;
2909 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2917 float getmousetarget
2920 void VM_M_getmousetarget(void)
2922 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2925 PRVM_G_FLOAT(OFS_RETURN) = 2;
2927 PRVM_G_FLOAT(OFS_RETURN) = 1;
2936 setkeydest(float dest)
2939 void VM_M_setkeydest(void)
2941 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2943 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2947 key_dest = key_game;
2951 key_dest = key_menu;
2955 // key_dest = key_message
2958 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2969 void VM_M_getkeydest(void)
2971 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2973 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2977 PRVM_G_FLOAT(OFS_RETURN) = 0;
2980 PRVM_G_FLOAT(OFS_RETURN) = 2;
2984 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2987 PRVM_G_FLOAT(OFS_RETURN) = 3;
2995 callfunction(...,string function_name)
2999 mfunction_t *PRVM_ED_FindFunction (const char *name);
3000 void VM_M_callfunction(void)
3006 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3008 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3011 PRVM_ERROR("VM_M_callfunction: null string !\n");
3013 VM_CheckEmptyString(s);
3015 func = PRVM_ED_FindFunction(s);
3018 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3019 else if (func->first_statement < 0)
3021 // negative statements are built in functions
3022 int builtinnumber = -func->first_statement;
3023 prog->xfunction->builtinsprofile++;
3024 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3025 prog->builtins[builtinnumber]();
3027 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3032 PRVM_ExecuteProgram(func - prog->functions,"");
3041 float isfunction(string function_name)
3044 mfunction_t *PRVM_ED_FindFunction (const char *name);
3045 void VM_M_isfunction(void)
3050 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3052 s = PRVM_G_STRING(OFS_PARM0);
3055 PRVM_ERROR("VM_M_isfunction: null string !\n");
3057 VM_CheckEmptyString(s);
3059 func = PRVM_ED_FindFunction(s);
3062 PRVM_G_FLOAT(OFS_RETURN) = false;
3064 PRVM_G_FLOAT(OFS_RETURN) = true;
3071 writetofile(float fhandle, entity ent)
3074 void VM_M_writetofile(void)
3079 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3081 filenum = PRVM_G_FLOAT(OFS_PARM0);
3082 if (filenum < 0 || filenum >= MAX_VMFILES)
3084 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3087 if (VM_FILES[filenum] == NULL)
3089 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3093 ent = PRVM_G_EDICT(OFS_PARM1);
3096 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3100 PRVM_ED_Write (VM_FILES[filenum], ent);
3107 vector getresolution(float number)
3110 extern unsigned short video_resolutions[][2];
3111 void VM_M_getresolution(void)
3114 VM_SAFEPARMCOUNT(1, VM_getresolution);
3116 nr = PRVM_G_FLOAT(OFS_PARM0);
3119 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3120 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3121 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3128 string keynumtostring(float keynum)
3131 void VM_M_keynumtostring(void)
3135 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3137 keynum = PRVM_G_FLOAT(OFS_PARM0);
3139 tmp = VM_GetTempString();
3141 strcpy(tmp, Key_KeynumToString(keynum));
3143 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3148 VM_M_findkeysforcommand
3150 string findkeysforcommand(string command)
3152 the returned string is an altstring
3155 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3157 void M_FindKeysForCommand(char *command, int *keys);
3158 void VM_M_findkeysforcommand(void)
3164 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3166 cmd = PRVM_G_STRING(OFS_PARM0);
3168 VM_CheckEmptyString(cmd);
3170 (ret = VM_GetTempString())[0] = 0;
3172 M_FindKeysForCommand(cmd, keys);
3174 for(i = 0; i < NUMKEYS; i++)
3175 ret = strcat(ret, va(" \'%i\'", keys[i]));
3177 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3182 VM_M_gethostcachecount
3184 float gethostcachevalue(float type)
3195 void VM_M_gethostcachevalue( void )
3198 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3200 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3202 type = PRVM_G_FLOAT( OFS_PARM0 );
3203 if( type < 0 || type > 4 )
3204 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3208 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3211 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3214 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3217 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3220 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3227 VM_M_gethostcachestring
3229 string gethostcachestring(float type, float hostnr)
3237 void VM_M_gethostcachestring(void)
3242 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3244 PRVM_G_INT(OFS_RETURN) = 0;
3246 type = PRVM_G_FLOAT(OFS_PARM0);
3248 if(type < 0 || type > 2)
3250 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3254 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3256 if(hostnr < 0 || hostnr >= hostCacheCount)
3258 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3263 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3264 else if( type == 1 )
3265 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3267 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3270 prvm_builtin_t vm_m_builtins[] = {
3271 0, // to be consistent with the old vm
3272 // common builtings (mostly)
3349 VM_search_getfilename, // 77
3366 VM_WriteEntity, // 408
3382 VM_drawresetcliparea,
3383 VM_getimagesize,// 460
3392 VM_M_setmousetarget,
3393 VM_M_getmousetarget,
3398 VM_M_keynumtostring,
3399 VM_M_findkeysforcommand,// 610
3400 VM_M_gethostcachevalue,
3401 VM_M_gethostcachestring,
3402 VM_M_parseentitydata // 613
3405 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3407 void VM_M_Cmd_Init(void)
3412 void VM_M_Cmd_Reset(void)