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)
100 float etof(entity ent)
101 entity ftoe(float num)
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, true))
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 ========================
844 float etof(entity ent)
845 ========================
849 VM_SAFEPARMCOUNT(1, VM_etof);
850 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
854 ========================
857 entity ftoe(float num)
858 ========================
863 VM_SAFEPARMCOUNT(1, VM_ftoe);
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, 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. 2 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)
2000 VM_SAFEPARMCOUNT(1,VM_strunzone);
2002 Mem_Free(PRVM_G_STRING(OFS_PARM0));
2007 VM_command (used by client and menu)
2009 clientcommand(float client, string s) (for client and menu)
2012 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2013 //this function originally written by KrimZon, made shorter by LordHavoc
2014 void VM_clcommand (void)
2016 client_t *temp_client;
2019 VM_SAFEPARMCOUNT(2,VM_clcommand);
2021 i = PRVM_G_FLOAT(OFS_PARM0);
2022 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2024 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2028 temp_client = host_client;
2029 host_client = svs.clients + i;
2030 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2031 host_client = temp_client;
2039 float tokenize(string s)
2042 //float(string s) tokenize = #441;
2043 // takes apart a string into individal words (access them with argv), returns how many
2044 // this function originally written by KrimZon, made shorter by LordHavoc
2045 static char **tokens = NULL;
2046 static int max_tokens, num_tokens = 0;
2047 void VM_tokenize (void)
2052 VM_SAFEPARMCOUNT(1,VM_tokenize);
2054 str = PRVM_G_STRING(OFS_PARM0);
2059 for (i=0;i<num_tokens;i++)
2065 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2066 max_tokens = strlen(str);
2068 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2070 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2071 strcpy(tokens[num_tokens], com_token);
2074 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2081 string argv(float n)
2084 //string(float n) argv = #442;
2085 // returns a word from the tokenized string (returns nothing for an invalid index)
2086 // this function originally written by KrimZon, made shorter by LordHavoc
2091 VM_SAFEPARMCOUNT(1,VM_argv);
2093 token_num = PRVM_G_FLOAT(OFS_PARM0);
2094 if (token_num >= 0 && token_num < num_tokens)
2095 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2097 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2101 //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
2102 void PF_setattachment (void)
2104 edict_t *e = G_EDICT(OFS_PARM0);
2105 edict_t *tagentity = G_EDICT(OFS_PARM1);
2106 char *tagname = G_STRING(OFS_PARM2);
2111 if (tagentity == NULL)
2112 tagentity = sv.edicts;
2114 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2116 v->edict = EDICT_TO_PROG(tagentity);
2118 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2121 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2123 modelindex = (int)tagentity->v->modelindex;
2124 if (modelindex >= 0 && modelindex < MAX_MODELS)
2126 model = sv.models[modelindex];
2127 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2128 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2129 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2131 // FIXME: use a model function to get tag info (need to handle skeletal)
2132 if (v->_float == 0 && model->alias.aliasnum_tags)
2133 for (i = 0;i < model->alias.aliasnum_tags;i++)
2134 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2137 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name);
2140 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity));
2151 void VM_isserver(void)
2153 VM_SAFEPARMCOUNT(0,VM_serverstate);
2155 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2165 void VM_clientcount(void)
2167 VM_SAFEPARMCOUNT(0,VM_clientcount);
2169 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2179 void VM_clientstate(void)
2181 VM_SAFEPARMCOUNT(0,VM_clientstate);
2183 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2190 float getostype(void)
2192 */ // not used at the moment -> not included in the common list
2193 void VM_getostype(void)
2195 VM_SAFEPARMCOUNT(0,VM_getostype);
2200 OS_MAC - not supported
2204 PRVM_G_FLOAT(OFS_RETURN) = 0;
2206 PRVM_G_FLOAT(OFS_RETURN) = 2;
2208 PRVM_G_FLOAT(OFS_RETURN) = 1;
2216 vector getmousepos()
2219 void VM_getmousepos(void)
2222 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2224 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2225 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2226 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2236 void VM_gettime(void)
2238 VM_SAFEPARMCOUNT(0,VM_gettime);
2240 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2247 loadfromdata(string data)
2250 void VM_loadfromdata(void)
2252 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2254 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2258 ========================
2259 VM_M_parseentitydata
2261 parseentitydata(entity ent, string data)
2262 ========================
2264 void VM_M_parseentitydata(void)
2269 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2271 // get edict and test it
2272 ent = PRVM_G_EDICT(OFS_PARM0);
2274 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2276 data = PRVM_G_STRING(OFS_PARM1);
2278 // parse the opening brace
2279 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2280 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2282 PRVM_ED_ParseEdict (data, ent);
2289 loadfromfile(string file)
2292 void VM_loadfromfile(void)
2297 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2299 filename = PRVM_G_STRING(OFS_PARM0);
2300 // .. is parent directory on many platforms
2301 // / is parent directory on Amiga
2302 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2303 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2304 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2306 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2307 PRVM_G_FLOAT(OFS_RETURN) = -4;
2311 // not conform with VM_fopen
2312 data = FS_LoadFile(filename, tempmempool, false);
2314 PRVM_G_FLOAT(OFS_RETURN) = -1;
2316 PRVM_ED_LoadFromFile(data);
2327 float mod(float val, float m)
2330 void VM_modulo(void)
2333 VM_SAFEPARMCOUNT(2,VM_module);
2335 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2336 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2338 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2341 void VM_Search_Init(void)
2343 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2346 void VM_Search_Reset(void)
2349 // reset the fssearch list
2350 for(i = 0; i < MAX_VMSEARCHES; i++)
2351 if(VM_SEARCHLIST[i])
2352 FS_FreeSearch(VM_SEARCHLIST[i]);
2353 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2360 float search_begin(string pattern, float caseinsensitive, float quiet)
2363 void VM_search_begin(void)
2367 int caseinsens, quiet;
2369 VM_SAFEPARMCOUNT(3, VM_search_begin);
2371 pattern = PRVM_G_STRING(OFS_PARM0);
2373 VM_CheckEmptyString(pattern);
2375 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2376 quiet = PRVM_G_FLOAT(OFS_PARM2);
2378 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2379 if(!VM_SEARCHLIST[handle])
2382 if(handle >= MAX_VMSEARCHES)
2384 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2385 PRVM_G_FLOAT(OFS_RETURN) = -2;
2389 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2390 PRVM_G_FLOAT(OFS_RETURN) = -1;
2392 PRVM_G_FLOAT(OFS_RETURN) = handle;
2399 void search_end(float handle)
2402 void VM_search_end(void)
2405 VM_SAFEPARMCOUNT(1, VM_search_end);
2407 handle = PRVM_G_FLOAT(OFS_PARM0);
2409 if(handle < 0 || handle >= MAX_VMSEARCHES)
2411 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2414 if(VM_SEARCHLIST[handle] == NULL)
2416 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2420 FS_FreeSearch(VM_SEARCHLIST[handle]);
2421 VM_SEARCHLIST[handle] = NULL;
2428 float search_getsize(float handle)
2431 void VM_search_getsize(void)
2434 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2436 handle = PRVM_G_FLOAT(OFS_PARM0);
2438 if(handle < 0 || handle >= MAX_VMSEARCHES)
2440 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2443 if(VM_SEARCHLIST[handle] == NULL)
2445 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2449 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2454 VM_search_getfilename
2456 string search_getfilename(float handle, float num)
2459 void VM_search_getfilename(void)
2461 int handle, filenum;
2463 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2465 handle = PRVM_G_FLOAT(OFS_PARM0);
2466 filenum = PRVM_G_FLOAT(OFS_PARM1);
2468 if(handle < 0 || handle >= MAX_VMSEARCHES)
2470 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2473 if(VM_SEARCHLIST[handle] == NULL)
2475 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2478 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2480 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2484 tmp = VM_GetTempString();
2485 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2487 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2494 string chr(float ascii)
2500 VM_SAFEPARMCOUNT(1, VM_chr);
2502 tmp = VM_GetTempString();
2503 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2506 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2509 //=============================================================================
2510 // Draw builtins (client & menu)
2516 float iscachedpic(string pic)
2519 void VM_iscachedpic(void)
2521 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2523 // drawq hasnt such a function, thus always return true
2524 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2531 string precache_pic(string pic)
2534 void VM_precache_pic(void)
2538 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2540 s = PRVM_G_STRING(OFS_PARM0);
2541 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2544 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2546 VM_CheckEmptyString (s);
2548 if(!Draw_CachePic(s))
2549 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2559 void VM_freepic(void)
2563 VM_SAFEPARMCOUNT(1,VM_freepic);
2565 s = PRVM_G_STRING(OFS_PARM0);
2568 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2570 VM_CheckEmptyString (s);
2579 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2582 void VM_drawcharacter(void)
2584 float *pos,*scale,*rgb;
2587 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2589 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2592 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2593 PRVM_G_FLOAT(OFS_RETURN) = -1;
2597 pos = PRVM_G_VECTOR(OFS_PARM0);
2598 scale = PRVM_G_VECTOR(OFS_PARM2);
2599 rgb = PRVM_G_VECTOR(OFS_PARM3);
2600 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2602 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2604 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2605 PRVM_G_FLOAT(OFS_RETURN) = -2;
2609 if(pos[2] || scale[2])
2610 Con_Printf("VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2612 if(!scale[0] || !scale[1])
2614 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2615 PRVM_G_FLOAT(OFS_RETURN) = -3;
2619 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2620 PRVM_G_FLOAT(OFS_RETURN) = 1;
2627 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2630 void VM_drawstring(void)
2632 float *pos,*scale,*rgb;
2635 VM_SAFEPARMCOUNT(6,VM_drawstring);
2637 string = PRVM_G_STRING(OFS_PARM1);
2640 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2641 PRVM_G_FLOAT(OFS_RETURN) = -1;
2645 VM_CheckEmptyString(string);
2647 pos = PRVM_G_VECTOR(OFS_PARM0);
2648 scale = PRVM_G_VECTOR(OFS_PARM2);
2649 rgb = PRVM_G_VECTOR(OFS_PARM3);
2650 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2652 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2654 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2655 PRVM_G_FLOAT(OFS_RETURN) = -2;
2659 if(!scale[0] || !scale[1])
2661 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2662 PRVM_G_FLOAT(OFS_RETURN) = -3;
2666 if(pos[2] || scale[2])
2667 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2669 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2670 PRVM_G_FLOAT(OFS_RETURN) = 1;
2676 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2679 void VM_drawpic(void)
2682 float *size, *pos, *rgb;
2685 VM_SAFEPARMCOUNT(6,VM_drawpic);
2687 pic = PRVM_G_STRING(OFS_PARM1);
2691 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2692 PRVM_G_FLOAT(OFS_RETURN) = -1;
2696 VM_CheckEmptyString (pic);
2698 // is pic cached ? no function yet for that
2701 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2702 PRVM_G_FLOAT(OFS_RETURN) = -4;
2706 pos = PRVM_G_VECTOR(OFS_PARM0);
2707 size = PRVM_G_VECTOR(OFS_PARM2);
2708 rgb = PRVM_G_VECTOR(OFS_PARM3);
2709 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2711 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2713 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2714 PRVM_G_FLOAT(OFS_RETURN) = -2;
2718 if(pos[2] || size[2])
2719 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2721 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2722 PRVM_G_FLOAT(OFS_RETURN) = 1;
2729 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2732 void VM_drawfill(void)
2734 float *size, *pos, *rgb;
2737 VM_SAFEPARMCOUNT(5,VM_drawfill);
2740 pos = PRVM_G_VECTOR(OFS_PARM0);
2741 size = PRVM_G_VECTOR(OFS_PARM1);
2742 rgb = PRVM_G_VECTOR(OFS_PARM2);
2743 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2745 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2747 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2748 PRVM_G_FLOAT(OFS_RETURN) = -2;
2752 if(pos[2] || size[2])
2753 Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2755 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2756 PRVM_G_FLOAT(OFS_RETURN) = 1;
2763 drawsetcliparea(float x, float y, float width, float height)
2766 void VM_drawsetcliparea(void)
2769 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2771 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2772 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2773 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2774 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2776 DrawQ_SetClipArea(x,y,w,h);
2781 VM_drawresetcliparea
2786 void VM_drawresetcliparea(void)
2788 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2790 DrawQ_ResetClipArea();
2797 vector getimagesize(string pic)
2800 void VM_getimagesize(void)
2805 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2807 p = PRVM_G_STRING(OFS_PARM0);
2810 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2812 VM_CheckEmptyString (p);
2814 pic = Draw_CachePic (p);
2816 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2817 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2818 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2821 void VM_Cmd_Init(void)
2823 // only init the stuff for the current prog
2824 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2829 void VM_Cmd_Reset(void)
2831 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2832 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2834 VM_Files_CloseAll();
2837 //============================================================================
2840 char *vm_sv_extensions =
2843 prvm_builtin_t vm_sv_builtins[] = {
2844 0 // to be consistent with the old vm
2847 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2849 void VM_SV_Cmd_Init(void)
2853 void VM_SV_Cmd_Reset(void)
2857 //============================================================================
2860 char *vm_cl_extensions =
2863 prvm_builtin_t vm_cl_builtins[] = {
2864 0 // to be consistent with the old vm
2867 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2869 void VM_CL_Cmd_Init(void)
2873 void VM_CL_Cmd_Reset(void)
2877 //============================================================================
2880 char *vm_m_extensions =
2887 setmousetarget(float target)
2890 void VM_M_setmousetarget(void)
2892 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2894 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2897 in_client_mouse = false;
2900 in_client_mouse = true;
2903 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2911 float getmousetarget
2914 void VM_M_getmousetarget(void)
2916 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2919 PRVM_G_FLOAT(OFS_RETURN) = 2;
2921 PRVM_G_FLOAT(OFS_RETURN) = 1;
2930 setkeydest(float dest)
2933 void VM_M_setkeydest(void)
2935 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2937 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2941 key_dest = key_game;
2945 key_dest = key_menu;
2949 // key_dest = key_message
2952 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2963 void VM_M_getkeydest(void)
2965 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2967 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2971 PRVM_G_FLOAT(OFS_RETURN) = 0;
2974 PRVM_G_FLOAT(OFS_RETURN) = 2;
2978 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2981 PRVM_G_FLOAT(OFS_RETURN) = 3;
2989 callfunction(...,string function_name)
2992 mfunction_t *PRVM_ED_FindFunction (const char *name);
2993 void VM_M_callfunction(void)
2999 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3001 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3004 PRVM_ERROR("VM_M_callfunction: null string !\n");
3006 VM_CheckEmptyString(s);
3008 func = PRVM_ED_FindFunction(s);
3011 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3012 else if (func->first_statement < 0)
3014 // negative statements are built in functions
3015 int builtinnumber = -func->first_statement;
3016 prog->xfunction->builtinsprofile++;
3017 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3018 prog->builtins[builtinnumber]();
3020 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3025 PRVM_ExecuteProgram(func - prog->functions,"");
3034 float isfunction(string function_name)
3037 mfunction_t *PRVM_ED_FindFunction (const char *name);
3038 void VM_M_isfunction(void)
3043 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3045 s = PRVM_G_STRING(OFS_PARM0);
3048 PRVM_ERROR("VM_M_isfunction: null string !\n");
3050 VM_CheckEmptyString(s);
3052 func = PRVM_ED_FindFunction(s);
3055 PRVM_G_FLOAT(OFS_RETURN) = false;
3057 PRVM_G_FLOAT(OFS_RETURN) = true;
3064 writetofile(float fhandle, entity ent)
3067 void VM_M_writetofile(void)
3072 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3074 filenum = PRVM_G_FLOAT(OFS_PARM0);
3075 if (filenum < 0 || filenum >= MAX_VMFILES)
3077 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3080 if (VM_FILES[filenum] == NULL)
3082 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3086 ent = PRVM_G_EDICT(OFS_PARM1);
3089 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3093 PRVM_ED_Write (VM_FILES[filenum], ent);
3100 vector getresolution(float number)
3103 extern unsigned short video_resolutions[][2];
3104 void VM_M_getresolution(void)
3107 VM_SAFEPARMCOUNT(1, VM_getresolution);
3109 nr = PRVM_G_FLOAT(OFS_PARM0);
3112 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3113 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3114 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3121 string keynumtostring(float keynum)
3124 void VM_M_keynumtostring(void)
3128 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3130 keynum = PRVM_G_FLOAT(OFS_PARM0);
3132 tmp = VM_GetTempString();
3134 strcpy(tmp, Key_KeynumToString(keynum));
3136 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3141 VM_M_findkeysforcommand
3143 string findkeysforcommand(string command)
3145 the returned string is an altstring
3148 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3150 void M_FindKeysForCommand(char *command, int *keys);
3151 void VM_M_findkeysforcommand(void)
3157 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3159 cmd = PRVM_G_STRING(OFS_PARM0);
3161 VM_CheckEmptyString(cmd);
3163 (ret = VM_GetTempString())[0] = 0;
3165 M_FindKeysForCommand(cmd, keys);
3167 for(i = 0; i < NUMKEYS; i++)
3168 ret = strcat(ret, va(" \'%i\'", keys[i]));
3170 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3175 VM_M_gethostcachecount
3177 float gethostcachevalue(float type)
3188 void VM_M_gethostcachevalue( void )
3191 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3193 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3195 type = PRVM_G_FLOAT( OFS_PARM0 );
3196 if( type < 0 || type > 4 )
3197 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3201 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3204 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3207 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3210 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3213 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3220 VM_M_gethostcachestring
3222 string gethostcachestring(float type, float hostnr)
3230 void VM_M_gethostcachestring(void)
3235 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3237 PRVM_G_INT(OFS_RETURN) = 0;
3239 type = PRVM_G_FLOAT(OFS_PARM0);
3241 if(type < 0 || type > 2)
3243 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3247 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3249 if(hostnr < 0 || hostnr >= hostCacheCount)
3251 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3256 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3257 else if( type == 1 )
3258 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3260 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3263 prvm_builtin_t vm_m_builtins[] = {
3264 0, // to be consistent with the old vm
3265 // common builtings (mostly)
3342 VM_search_getfilename, // 77
3359 VM_WriteEntity, // 408
3375 VM_drawresetcliparea,
3376 VM_getimagesize,// 460
3385 VM_M_setmousetarget,
3386 VM_M_getmousetarget,
3391 VM_M_keynumtostring,
3392 VM_M_findkeysforcommand,// 610
3393 VM_M_gethostcachevalue,
3394 VM_M_gethostcachestring,
3395 VM_M_parseentitydata // 613
3398 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3400 void VM_M_Cmd_Init(void)
3405 void VM_M_Cmd_Reset(void)