2 // Basically every vm builtin cmd should be in here.
3 // All 3 builtin and extension lists can be found here
4 // cause large (I think they will) parts are from pr_cmds the same copyright like in pr_cmds
9 ============================================================================
13 checkextension(string)
18 sprint(float clientnum,...[string])
19 centerprint(...[string])
20 vector normalize(vector)
22 float vectoyaw(vector)
23 vector vectoangles(vector)
27 cvar_set (string,string)
33 float stof(...[string])
36 entity find(entity start, .string field, string match)
38 entity findfloat(entity start, .float field, float match)
39 entity findentity(entity start, .entity field, entity match)
41 entity findchain(.string field, string match)
43 entity findchainfloat(.string field, float match)
44 entity findchainentity(.string field, entity match)
46 string precache_file(string)
47 string precache_sound (string sample)
55 entity nextent(entity)
60 float registercvar (string name, string value, float flags)
61 float min(float a, float b, ...[float])
62 float max(float a, float b, ...[float])
63 float bound(float min, float value, float max)
64 float pow(float a, float b)
65 copyentity(entity src, entity dst)
66 float fopen(string filename, float mode)
68 string fgets(float fhandle)
69 fputs(float fhandle, string s)
70 float strlen(string s)
71 string strcat(string,string,...[string])
72 string substring(string s, float start, float length)
74 string strzone(string s)
76 float tokenize(string s)
81 clientcommand(float client, string s) (for client and menu)
82 changelevel(string map)
83 localsound(string sample)
86 loadfromdata(string data)
87 loadfromfile(string file)
88 float mod(float val, float m)
89 const string str_cvar (string)
93 float search_begin(string pattern, float caseinsensitive, float quiet)
94 void search_end(float handle)
95 float search_getsize(float handle)
96 string search_getfilename(float handle, float num)
98 string chr(float ascii)
103 perhaps only : Menu : WriteMsg
104 ===============================
106 WriteByte(float data, float dest, float desto)
107 WriteChar(float data, float dest, float desto)
108 WriteShort(float data, float dest, float desto)
109 WriteLong(float data, float dest, float desto)
110 WriteAngle(float data, float dest, float desto)
111 WriteCoord(float data, float dest, float desto)
112 WriteString(string data, float dest, float desto)
113 WriteEntity(entity data, float dest, float desto)
115 Client & Menu : draw functions
116 ===============================
118 float iscachedpic(string pic)
119 string precache_pic(string pic)
121 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
122 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
123 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
124 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
125 drawsetcliparea(float x, float y, float width, float height)
127 vector getimagesize(string pic)
130 ==============================================================================
134 setkeydest(float dest)
136 setmousetarget(float target)
137 float getmousetarget(void)
139 callfunction(...,string function_name)
140 writetofile(float fhandle, entity ent)
141 float isfunction(string function_name)
142 vector getresolution(float number)
143 string keynumtostring(float keynum)
144 string findkeysforcommand(string command)
145 float gethostcachevalue(float type)
146 string gethostcachestring(float type, float hostnr)
148 parseentitydata(entity ent, string data)
151 #include "quakedef.h"
152 #include "progdefs.h"
154 #include "clprogdefs.h"
155 #include "mprogdefs.h"
157 //============================================================================
158 // nice helper macros
160 #ifndef VM_NOPARMCHECK
161 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
163 #define VM_SAFEPARMCOUNT(p,f)
166 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
168 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
170 #define e10 0,0,0,0,0,0,0,0,0,0
171 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
172 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
174 //============================================================================
177 // string zone mempool
178 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
180 // temp string handling
181 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
182 #define VM_STRINGTEMP_BUFFERS 16
183 #define VM_STRINGTEMP_LENGTH 4096
184 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
185 static int vm_string_tempindex = 0;
188 #define MAX_VMFILES 256
189 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
190 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
192 qfile_t *vm_files[MAX_PRVMFILES];
194 // qc fs search handling
195 #define MAX_VMSEARCHES 128
196 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
197 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
199 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
201 static char *VM_GetTempString(void)
204 s = vm_string_temp[vm_string_tempindex];
205 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
209 void VM_CheckEmptyString (char *s)
212 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
215 //============================================================================
218 void VM_VarString(int first, char *out, int outlength)
224 outend = out + outlength - 1;
225 for (i = first;i < prog->argc && out < outend;i++)
227 s = PRVM_G_STRING((OFS_PARM0+i*3));
228 while (out < outend && *s)
238 returns true if the extension is supported by the server
240 checkextension(extensionname)
244 // kind of helper function
245 static qboolean checkextension(char *name)
251 for (e = prog->extensionstring;*e;e++)
258 while (*e && *e != ' ')
260 if (e - start == len)
261 if (!strncasecmp(start, name, len))
269 void VM_checkextension (void)
271 VM_SAFEPARMCOUNT(1,VM_checkextension);
273 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
280 This is a TERMINAL error, which will kill off the entire prog.
289 char string[VM_STRINGTEMP_LENGTH];
291 VM_VarString(0, string, sizeof(string));
292 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
295 ed = PRVM_G_EDICT(prog->self->ofs);
299 PRVM_ERROR ("%s: Program error", PRVM_NAME);
306 Dumps out self, then an error message. The program is aborted and self is
307 removed, but the level can continue.
312 void VM_objerror (void)
315 char string[VM_STRINGTEMP_LENGTH];
317 VM_VarString(0, string, sizeof(string));
318 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
321 ed = PRVM_G_EDICT (prog->self->ofs);
327 // objerror has to display the object fields -> else call
328 PRVM_ERROR ("VM_objecterror: self not defined !\n");
333 VM_print (actually used only by client and menu)
342 char string[VM_STRINGTEMP_LENGTH];
344 VM_VarString(0, string, sizeof(string));
352 broadcast print to everyone on server
357 void VM_bprint (void)
359 char string[VM_STRINGTEMP_LENGTH];
363 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
367 VM_VarString(0, string, sizeof(string));
368 SV_BroadcastPrint(string);
373 VM_sprint (menu & client but only if server.active == true)
375 single print to a specific client
377 sprint(float clientnum,...[string])
380 void VM_sprint (void)
384 char string[VM_STRINGTEMP_LENGTH];
386 //find client for this entity
387 clientnum = PRVM_G_FLOAT(OFS_PARM0);
388 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
390 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
394 client = svs.clients + clientnum;
395 VM_VarString(1, string, sizeof(string));
396 MSG_WriteChar(&client->message,svc_print);
397 MSG_WriteString(&client->message, string);
404 single print to the screen
406 centerprint(clientent, value)
409 void VM_centerprint (void)
411 char string[VM_STRINGTEMP_LENGTH];
413 VM_VarString(0, string, sizeof(string));
414 SCR_CenterPrint(string);
421 vector normalize(vector)
424 void VM_normalize (void)
430 VM_SAFEPARMCOUNT(1,VM_normalize);
432 value1 = PRVM_G_VECTOR(OFS_PARM0);
434 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
438 newvalue[0] = newvalue[1] = newvalue[2] = 0;
442 newvalue[0] = value1[0] * new;
443 newvalue[1] = value1[1] * new;
444 newvalue[2] = value1[2] * new;
447 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
462 VM_SAFEPARMCOUNT(1,VM_vlen);
464 value1 = PRVM_G_VECTOR(OFS_PARM0);
466 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
469 PRVM_G_FLOAT(OFS_RETURN) = new;
476 float vectoyaw(vector)
479 void VM_vectoyaw (void)
484 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
486 value1 = PRVM_G_VECTOR(OFS_PARM0);
488 if (value1[1] == 0 && value1[0] == 0)
492 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
497 PRVM_G_FLOAT(OFS_RETURN) = yaw;
505 vector vectoangles(vector)
508 void VM_vectoangles (void)
514 VM_SAFEPARMCOUNT(1,VM_vectoangles);
516 value1 = PRVM_G_VECTOR(OFS_PARM0);
518 if (value1[1] == 0 && value1[0] == 0)
528 // LordHavoc: optimized a bit
531 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
535 else if (value1[1] > 0)
540 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
541 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
546 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
547 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
548 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
555 Returns a number from 0<= num < 1
560 void VM_random (void)
564 VM_SAFEPARMCOUNT(0,VM_random);
566 num = (rand ()&0x7fff) / ((float)0x7fff);
568 PRVM_G_FLOAT(OFS_RETURN) = num;
575 Each entity can have eight independant sound sources, like voice,
578 Channel 0 is an auto-allocate channel, the others override anything
579 already running on that entity/channel pair.
581 An attenuation of 0 will play full volume everywhere in the level.
582 Larger attenuations will drop off.
595 entity = G_EDICT(OFS_PARM0);
596 channel = G_FLOAT(OFS_PARM1);
597 sample = G_STRING(OFS_PARM2);
598 volume = G_FLOAT(OFS_PARM3) * 255;
599 attenuation = G_FLOAT(OFS_PARM4);
601 if (volume < 0 || volume > 255)
602 Host_Error ("SV_StartSound: volume = %i", volume);
604 if (attenuation < 0 || attenuation > 4)
605 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
607 if (channel < 0 || channel > 7)
608 Host_Error ("SV_StartSound: channel = %i", channel);
610 SV_StartSound (entity, channel, sample, volume, attenuation);
618 localsound(string sample)
621 void VM_localsound(void)
625 VM_SAFEPARMCOUNT(1,VM_localsound);
627 s = PRVM_G_STRING(OFS_PARM0);
629 if(!S_LocalSound (s))
631 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
632 PRVM_G_FLOAT(OFS_RETURN) = -4;
636 PRVM_G_FLOAT(OFS_RETURN) = 1;
648 PRVM_ERROR ("%s: break statement", PRVM_NAME);
651 //============================================================================
657 Sends text over to the client's execution buffer
659 [localcmd (string) or]
663 void VM_localcmd (void)
665 VM_SAFEPARMCOUNT(1,VM_localcmd);
667 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
679 VM_SAFEPARMCOUNT(1,VM_cvar);
681 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
688 const string str_cvar (string)
691 void VM_str_cvar(void)
694 const char *cvar_string;
695 VM_SAFEPARMCOUNT(1,VM_str_cvar);
697 name = PRVM_G_STRING(OFS_PARM0);
700 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
702 VM_CheckEmptyString(name);
704 out = VM_GetTempString();
706 cvar_string = Cvar_VariableString(name);
708 strcpy(out, cvar_string);
710 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
717 void cvar_set (string,string)
720 void VM_cvar_set (void)
722 VM_SAFEPARMCOUNT(2,VM_cvar_set);
724 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
734 void VM_dprint (void)
736 char string[VM_STRINGTEMP_LENGTH];
737 if (developer.integer)
739 VM_VarString(0, string, sizeof(string));
740 Con_Printf("%s: %s", PRVM_NAME, string);
757 VM_SAFEPARMCOUNT(1, VM_ftos);
759 v = PRVM_G_FLOAT(OFS_PARM0);
761 s = VM_GetTempString();
762 if ((float)((int)v) == v)
763 sprintf(s, "%i", (int)v);
766 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
781 VM_SAFEPARMCOUNT(1,VM_fabs);
783 v = PRVM_G_FLOAT(OFS_PARM0);
784 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
799 VM_SAFEPARMCOUNT(1,VM_vtos);
801 s = VM_GetTempString();
802 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]);
803 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
818 VM_SAFEPARMCOUNT(1, VM_etos);
820 s = VM_GetTempString();
821 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
822 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
829 float stof(...[string])
834 char string[VM_STRINGTEMP_LENGTH];
835 VM_VarString(0, string, sizeof(string));
836 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
840 ========================
844 ========================
848 VM_SAFEPARMCOUNT(1, VM_itof);
849 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
853 ========================
857 ========================
862 VM_SAFEPARMCOUNT(1, VM_ftoi);
864 ent = PRVM_G_FLOAT(OFS_PARM0);
865 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
866 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
868 PRVM_G_INT(OFS_RETURN) = ent;
882 prog->xfunction->builtinsprofile += 20;
883 ed = PRVM_ED_Alloc();
895 void VM_remove (void)
898 prog->xfunction->builtinsprofile += 20;
900 VM_SAFEPARMCOUNT(1, VM_remove);
902 ed = PRVM_G_EDICT(OFS_PARM0);
903 // if (ed == prog->edicts)
904 // PRVM_ERROR ("remove: tried to remove world\n");
905 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
906 // Host_Error("remove: tried to remove a client\n");
914 entity find(entity start, .string field, string match)
925 VM_SAFEPARMCOUNT(3,VM_find);
927 e = PRVM_G_EDICTNUM(OFS_PARM0);
928 f = PRVM_G_INT(OFS_PARM1);
929 s = PRVM_G_STRING(OFS_PARM2);
933 // return reserved edict 0 (could be used for whatever the prog wants)
934 VM_RETURN_EDICT(prog->edicts);
938 for (e++ ; e < prog->num_edicts ; e++)
940 prog->xfunction->builtinsprofile++;
941 ed = PRVM_EDICT_NUM(e);
944 t = PRVM_E_STRING(ed,f);
954 VM_RETURN_EDICT(prog->edicts);
961 entity findfloat(entity start, .float field, float match)
962 entity findentity(entity start, .entity field, entity match)
965 // LordHavoc: added this for searching float, int, and entity reference fields
966 void VM_findfloat (void)
973 VM_SAFEPARMCOUNT(3,VM_findfloat);
975 e = PRVM_G_EDICTNUM(OFS_PARM0);
976 f = PRVM_G_INT(OFS_PARM1);
977 s = PRVM_G_FLOAT(OFS_PARM2);
979 for (e++ ; e < prog->num_edicts ; e++)
981 prog->xfunction->builtinsprofile++;
982 ed = PRVM_EDICT_NUM(e);
985 if (PRVM_E_FLOAT(ed,f) == s)
992 VM_RETURN_EDICT(prog->edicts);
999 entity findchain(.string field, string match)
1002 int PRVM_ED_FindFieldOffset(const char *field);
1003 // chained search for strings in entity fields
1004 // entity(.string field, string match) findchain = #402;
1005 void VM_findchain (void)
1011 prvm_edict_t *ent, *chain;
1013 VM_SAFEPARMCOUNT(2,VM_findchain);
1015 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1016 if(!prog->flag & PRVM_FE_CHAIN)
1017 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1019 chain_of = PRVM_ED_FindFieldOffset ("chain");
1021 chain = prog->edicts;
1023 f = PRVM_G_INT(OFS_PARM0);
1024 s = PRVM_G_STRING(OFS_PARM1);
1027 VM_RETURN_EDICT(prog->edicts);
1031 ent = PRVM_NEXT_EDICT(prog->edicts);
1032 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1034 prog->xfunction->builtinsprofile++;
1037 t = PRVM_E_STRING(ent,f);
1043 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1047 VM_RETURN_EDICT(chain);
1054 entity findchainfloat(.string field, float match)
1055 entity findchainentity(.string field, entity match)
1058 // LordHavoc: chained search for float, int, and entity reference fields
1059 // entity(.string field, float match) findchainfloat = #403;
1060 void VM_findchainfloat (void)
1066 prvm_edict_t *ent, *chain;
1068 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1070 if(!prog->flag & PRVM_FE_CHAIN)
1071 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1073 chain_of = PRVM_ED_FindFieldOffset ("chain");
1075 chain = (prvm_edict_t *)prog->edicts;
1077 f = PRVM_G_INT(OFS_PARM0);
1078 s = PRVM_G_FLOAT(OFS_PARM1);
1080 ent = PRVM_NEXT_EDICT(prog->edicts);
1081 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1083 prog->xfunction->builtinsprofile++;
1086 if (PRVM_E_FLOAT(ent,f) != s)
1089 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1093 VM_RETURN_EDICT(chain);
1100 string precache_file(string)
1103 void VM_precache_file (void)
1104 { // precache_file is only used to copy files with qcc, it does nothing
1105 VM_SAFEPARMCOUNT(1,VM_precache_file);
1107 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1114 used instead of the other VM_precache_* functions in the builtin list
1118 void VM_precache_error (void)
1120 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1127 string precache_sound (string sample)
1130 void VM_precache_sound (void)
1134 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1136 s = PRVM_G_STRING(OFS_PARM0);
1137 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1138 VM_CheckEmptyString (s);
1140 if(!S_PrecacheSound (s,true, true))
1141 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1151 void VM_coredump (void)
1153 VM_SAFEPARMCOUNT(0,VM_coredump);
1155 Cbuf_AddText("prvm_edicts ");
1156 Cbuf_AddText(PRVM_NAME);
1167 void PRVM_StackTrace(void);
1168 void VM_stackdump (void)
1170 VM_SAFEPARMCOUNT(0, VM_stackdump);
1185 VM_SAFEPARMCOUNT(0, VM_crash);
1187 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1197 void VM_traceon (void)
1199 VM_SAFEPARMCOUNT(0,VM_traceon);
1211 void VM_traceoff (void)
1213 VM_SAFEPARMCOUNT(0,VM_traceoff);
1215 prog->trace = false;
1225 void VM_eprint (void)
1227 VM_SAFEPARMCOUNT(1,VM_eprint);
1229 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1243 VM_SAFEPARMCOUNT(1,VM_rint);
1245 f = PRVM_G_FLOAT(OFS_PARM0);
1247 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1249 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1259 void VM_floor (void)
1261 VM_SAFEPARMCOUNT(1,VM_floor);
1263 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1275 VM_SAFEPARMCOUNT(1,VM_ceil);
1277 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1285 entity nextent(entity)
1288 void VM_nextent (void)
1293 i = PRVM_G_EDICTNUM(OFS_PARM0);
1296 prog->xfunction->builtinsprofile++;
1298 if (i == prog->num_edicts)
1300 VM_RETURN_EDICT(prog->edicts);
1303 ent = PRVM_EDICT_NUM(i);
1304 if (!ent->p.e->free)
1306 VM_RETURN_EDICT(ent);
1313 ===============================================================================
1316 used only for client and menu
1317 severs uses VM_SV_...
1319 Write*(* data, float type, float to)
1321 ===============================================================================
1324 #define MSG_BROADCAST 0 // unreliable to all
1325 #define MSG_ONE 1 // reliable to one (msg_entity)
1326 #define MSG_ALL 2 // reliable to all
1327 #define MSG_INIT 3 // write to the init string
1329 sizebuf_t *VM_WriteDest (void)
1335 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1337 dest = G_FLOAT(OFS_PARM1);
1341 return &sv.datagram;
1344 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1345 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1346 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1348 return &svs.clients[destclient].message;
1351 return &sv.reliable_datagram;
1357 PRVM_ERROR ("WriteDest: bad destination");
1364 void VM_WriteByte (void)
1366 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1369 void VM_WriteChar (void)
1371 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1374 void VM_WriteShort (void)
1376 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1379 void VM_WriteLong (void)
1381 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1384 void VM_WriteAngle (void)
1386 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1389 void VM_WriteCoord (void)
1391 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1394 void VM_WriteString (void)
1396 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1399 void VM_WriteEntity (void)
1401 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1404 //=============================================================================
1411 changelevel(string map)
1414 void VM_changelevel (void)
1418 VM_SAFEPARMCOUNT(1, VM_changelevel);
1422 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1426 // make sure we don't issue two changelevels
1427 if (svs.changelevel_issued)
1429 svs.changelevel_issued = true;
1431 s = G_STRING(OFS_PARM0);
1432 Cbuf_AddText (va("changelevel %s\n",s));
1444 VM_SAFEPARMCOUNT(1,VM_sin);
1445 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1456 VM_SAFEPARMCOUNT(1,VM_cos);
1457 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1469 VM_SAFEPARMCOUNT(1,VM_sqrt);
1470 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1477 Returns a vector of length < 1 and > 0
1482 void VM_randomvec (void)
1487 VM_SAFEPARMCOUNT(0, VM_randomvec);
1492 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1493 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1494 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1496 while (DotProduct(temp, temp) >= 1);
1497 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1500 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1501 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1502 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1503 // length returned always > 0
1504 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1505 VectorScale(temp,length, temp);*/
1506 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1509 //=============================================================================
1515 float registercvar (string name, string value, float flags)
1518 void VM_registercvar (void)
1523 VM_SAFEPARMCOUNT(3,VM_registercvar);
1525 name = PRVM_G_STRING(OFS_PARM0);
1526 value = PRVM_G_STRING(OFS_PARM1);
1527 flags = PRVM_G_FLOAT(OFS_PARM2);
1528 PRVM_G_FLOAT(OFS_RETURN) = 0;
1530 if(flags > CVAR_MAXFLAGSVAL)
1533 // first check to see if it has already been defined
1534 if (Cvar_FindVar (name))
1537 // check for overlap with a command
1538 if (Cmd_Exists (name))
1540 Con_Printf("VM_registercvar: %s is a command\n", name);
1544 Cvar_Get(name, value, flags);
1546 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1553 returns the minimum of two supplied floats
1555 float min(float a, float b, ...[float])
1560 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1561 if (prog->argc == 2)
1562 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1563 else if (prog->argc >= 3)
1566 float f = PRVM_G_FLOAT(OFS_PARM0);
1567 for (i = 1;i < prog->argc;i++)
1568 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1569 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1570 PRVM_G_FLOAT(OFS_RETURN) = f;
1573 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1580 returns the maximum of two supplied floats
1582 float max(float a, float b, ...[float])
1587 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1588 if (prog->argc == 2)
1589 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1590 else if (prog->argc >= 3)
1593 float f = PRVM_G_FLOAT(OFS_PARM0);
1594 for (i = 1;i < prog->argc;i++)
1595 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1596 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1597 G_FLOAT(OFS_RETURN) = f;
1600 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1607 returns number bounded by supplied range
1609 float bound(float min, float value, float max)
1612 void VM_bound (void)
1614 VM_SAFEPARMCOUNT(3,VM_bound);
1615 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1622 returns a raised to power b
1624 float pow(float a, float b)
1629 VM_SAFEPARMCOUNT(2,VM_pow);
1630 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1637 copies data from one entity to another
1639 copyentity(entity src, entity dst)
1642 void VM_copyentity (void)
1644 prvm_edict_t *in, *out;
1645 VM_SAFEPARMCOUNT(2,VM_copyentity);
1646 in = PRVM_G_EDICT(OFS_PARM0);
1647 out = PRVM_G_EDICT(OFS_PARM1);
1648 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1655 sets the color of a client and broadcasts the update to all connected clients
1657 setcolor(clientent, value)
1660 /*void PF_setcolor (void)
1666 entnum = G_EDICTNUM(OFS_PARM0);
1667 i = G_FLOAT(OFS_PARM1);
1669 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1671 Con_Print("tried to setcolor a non-client\n");
1675 client = svs.clients + entnum-1;
1676 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1679 client->old_colors = i;
1680 client->edict->v->team = (i & 15) + 1;
1682 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1683 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1684 MSG_WriteByte (&sv.reliable_datagram, i);
1687 void VM_Files_Init(void)
1689 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1692 void VM_Files_CloseAll(void)
1695 for (i = 0;i < MAX_VMFILES;i++)
1698 FS_Close(VM_FILES[i]);
1699 //VM_FILES[i] = NULL;
1701 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1708 float fopen(string filename, float mode)
1711 // float(string filename, float mode) fopen = #110;
1712 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1713 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1717 char *modestring, *filename;
1719 VM_SAFEPARMCOUNT(2,VM_fopen);
1721 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1722 if (VM_FILES[filenum] == NULL)
1724 if (filenum >= MAX_VMFILES)
1726 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1727 PRVM_G_FLOAT(OFS_RETURN) = -2;
1730 mode = PRVM_G_FLOAT(OFS_PARM1);
1733 case 0: // FILE_READ
1736 case 1: // FILE_APPEND
1739 case 2: // FILE_WRITE
1743 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1744 PRVM_G_FLOAT(OFS_RETURN) = -3;
1747 filename = PRVM_G_STRING(OFS_PARM0);
1748 // .. is parent directory on many platforms
1749 // / is parent directory on Amiga
1750 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1751 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1752 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1754 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1755 PRVM_G_FLOAT(OFS_RETURN) = -4;
1758 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1759 if (VM_FILES[filenum] == NULL && mode == 0)
1760 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1762 if (VM_FILES[filenum] == NULL)
1763 PRVM_G_FLOAT(OFS_RETURN) = -1;
1765 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1772 fclose(float fhandle)
1775 //void(float fhandle) fclose = #111; // closes a file
1776 void VM_fclose(void)
1780 VM_SAFEPARMCOUNT(1,VM_fclose);
1782 filenum = PRVM_G_FLOAT(OFS_PARM0);
1783 if (filenum < 0 || filenum >= MAX_VMFILES)
1785 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1788 if (VM_FILES[filenum] == NULL)
1790 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1793 FS_Close(VM_FILES[filenum]);
1794 VM_FILES[filenum] = NULL;
1801 string fgets(float fhandle)
1804 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1808 static char string[VM_STRINGTEMP_LENGTH];
1811 VM_SAFEPARMCOUNT(1,VM_fgets);
1813 filenum = PRVM_G_FLOAT(OFS_PARM0);
1814 if (filenum < 0 || filenum >= MAX_VMFILES)
1816 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1819 if (VM_FILES[filenum] == NULL)
1821 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1827 c = FS_Getc(VM_FILES[filenum]);
1828 if (c == '\r' || c == '\n' || c < 0)
1830 if (end < VM_STRINGTEMP_LENGTH - 1)
1834 // remove \n following \r
1836 c = FS_Getc(VM_FILES[filenum]);
1837 if (developer.integer)
1838 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1840 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1842 PRVM_G_INT(OFS_RETURN) = 0;
1849 fputs(float fhandle, string s)
1852 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1856 char string[VM_STRINGTEMP_LENGTH];
1859 VM_SAFEPARMCOUNT(2,VM_fputs);
1861 filenum = PRVM_G_FLOAT(OFS_PARM0);
1862 if (filenum < 0 || filenum >= MAX_VMFILES)
1864 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1867 if (VM_FILES[filenum] == NULL)
1869 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1872 VM_VarString(1, string, sizeof(string));
1873 if ((stringlength = strlen(string)))
1874 FS_Write(VM_FILES[filenum], string, stringlength);
1875 if (developer.integer)
1876 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1883 float strlen(string s)
1886 //float(string s) strlen = #114; // returns how many characters are in a string
1887 void VM_strlen(void)
1891 VM_SAFEPARMCOUNT(1,VM_strlen);
1893 s = PRVM_G_STRING(OFS_PARM0);
1895 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1897 PRVM_G_FLOAT(OFS_RETURN) = 0;
1904 string strcat(string,string,...[string])
1907 //string(string s1, string s2) strcat = #115;
1908 // concatenates two strings (for example "abc", "def" would return "abcdef")
1909 // and returns as a tempstring
1910 void VM_strcat(void)
1915 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1917 s = VM_GetTempString();
1918 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1919 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1926 string substring(string s, float start, float length)
1929 // string(string s, float start, float length) substring = #116;
1930 // returns a section of a string as a tempstring
1931 void VM_substring(void)
1933 int i, start, length;
1936 VM_SAFEPARMCOUNT(3,VM_substring);
1938 string = VM_GetTempString();
1939 s = PRVM_G_STRING(OFS_PARM0);
1940 start = PRVM_G_FLOAT(OFS_PARM1);
1941 length = PRVM_G_FLOAT(OFS_PARM2);
1944 for (i = 0;i < start && *s;i++, s++);
1945 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1948 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1955 vector stov(string s)
1958 //vector(string s) stov = #117; // returns vector value from a string
1961 char string[VM_STRINGTEMP_LENGTH];
1963 VM_SAFEPARMCOUNT(1,VM_stov);
1965 VM_VarString(0, string, sizeof(string));
1966 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1973 string strzone(string s)
1976 //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)
1977 void VM_strzone(void)
1981 VM_SAFEPARMCOUNT(1,VM_strzone);
1983 in = PRVM_G_STRING(OFS_PARM0);
1984 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1986 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1996 //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!!!)
1997 void VM_strunzone(void)
2000 VM_SAFEPARMCOUNT(1,VM_strunzone);
2002 str = PRVM_G_STRING(OFS_PARM0);
2003 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2004 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2011 VM_command (used by client and menu)
2013 clientcommand(float client, string s) (for client and menu)
2016 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2017 //this function originally written by KrimZon, made shorter by LordHavoc
2018 void VM_clcommand (void)
2020 client_t *temp_client;
2023 VM_SAFEPARMCOUNT(2,VM_clcommand);
2025 i = PRVM_G_FLOAT(OFS_PARM0);
2026 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2028 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2032 temp_client = host_client;
2033 host_client = svs.clients + i;
2034 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2035 host_client = temp_client;
2043 float tokenize(string s)
2046 //float(string s) tokenize = #441;
2047 // takes apart a string into individal words (access them with argv), returns how many
2048 // this function originally written by KrimZon, made shorter by LordHavoc
2049 static char **tokens = NULL;
2050 static int max_tokens, num_tokens = 0;
2051 void VM_tokenize (void)
2056 VM_SAFEPARMCOUNT(1,VM_tokenize);
2058 str = PRVM_G_STRING(OFS_PARM0);
2063 for (i=0;i<num_tokens;i++)
2069 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2070 max_tokens = strlen(str);
2072 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2074 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2075 strcpy(tokens[num_tokens], com_token);
2078 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2085 string argv(float n)
2088 //string(float n) argv = #442;
2089 // returns a word from the tokenized string (returns nothing for an invalid index)
2090 // this function originally written by KrimZon, made shorter by LordHavoc
2095 VM_SAFEPARMCOUNT(1,VM_argv);
2097 token_num = PRVM_G_FLOAT(OFS_PARM0);
2098 if (token_num >= 0 && token_num < num_tokens)
2099 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2101 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2105 //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)
2106 void PF_setattachment (void)
2108 edict_t *e = G_EDICT(OFS_PARM0);
2109 edict_t *tagentity = G_EDICT(OFS_PARM1);
2110 char *tagname = G_STRING(OFS_PARM2);
2115 if (tagentity == NULL)
2116 tagentity = sv.edicts;
2118 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2120 v->edict = EDICT_TO_PROG(tagentity);
2122 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2125 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2127 modelindex = (int)tagentity->v->modelindex;
2128 if (modelindex >= 0 && modelindex < MAX_MODELS)
2130 model = sv.models[modelindex];
2131 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2132 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2133 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2135 // FIXME: use a model function to get tag info (need to handle skeletal)
2136 if (v->_float == 0 && model->alias.aliasnum_tags)
2137 for (i = 0;i < model->alias.aliasnum_tags;i++)
2138 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2141 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);
2144 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));
2155 void VM_isserver(void)
2157 VM_SAFEPARMCOUNT(0,VM_serverstate);
2159 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2169 void VM_clientcount(void)
2171 VM_SAFEPARMCOUNT(0,VM_clientcount);
2173 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2183 void VM_clientstate(void)
2185 VM_SAFEPARMCOUNT(0,VM_clientstate);
2187 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2194 float getostype(void)
2196 */ // not used at the moment -> not included in the common list
2197 void VM_getostype(void)
2199 VM_SAFEPARMCOUNT(0,VM_getostype);
2204 OS_MAC - not supported
2208 PRVM_G_FLOAT(OFS_RETURN) = 0;
2210 PRVM_G_FLOAT(OFS_RETURN) = 2;
2212 PRVM_G_FLOAT(OFS_RETURN) = 1;
2220 vector getmousepos()
2223 void VM_getmousepos(void)
2226 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2228 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2229 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2230 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2240 void VM_gettime(void)
2242 VM_SAFEPARMCOUNT(0,VM_gettime);
2244 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2251 loadfromdata(string data)
2254 void VM_loadfromdata(void)
2256 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2258 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2262 ========================
2263 VM_M_parseentitydata
2265 parseentitydata(entity ent, string data)
2266 ========================
2268 void VM_M_parseentitydata(void)
2273 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2275 // get edict and test it
2276 ent = PRVM_G_EDICT(OFS_PARM0);
2278 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2280 data = PRVM_G_STRING(OFS_PARM1);
2282 // parse the opening brace
2283 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2284 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2286 PRVM_ED_ParseEdict (data, ent);
2293 loadfromfile(string file)
2296 void VM_loadfromfile(void)
2301 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2303 filename = PRVM_G_STRING(OFS_PARM0);
2304 // .. is parent directory on many platforms
2305 // / is parent directory on Amiga
2306 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2307 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2308 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2310 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2311 PRVM_G_FLOAT(OFS_RETURN) = -4;
2315 // not conform with VM_fopen
2316 data = FS_LoadFile(filename, tempmempool, false);
2318 PRVM_G_FLOAT(OFS_RETURN) = -1;
2320 PRVM_ED_LoadFromFile(data);
2331 float mod(float val, float m)
2334 void VM_modulo(void)
2337 VM_SAFEPARMCOUNT(2,VM_module);
2339 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2340 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2342 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2345 void VM_Search_Init(void)
2347 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2350 void VM_Search_Reset(void)
2353 // reset the fssearch list
2354 for(i = 0; i < MAX_VMSEARCHES; i++)
2355 if(VM_SEARCHLIST[i])
2356 FS_FreeSearch(VM_SEARCHLIST[i]);
2357 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2364 float search_begin(string pattern, float caseinsensitive, float quiet)
2367 void VM_search_begin(void)
2371 int caseinsens, quiet;
2373 VM_SAFEPARMCOUNT(3, VM_search_begin);
2375 pattern = PRVM_G_STRING(OFS_PARM0);
2377 VM_CheckEmptyString(pattern);
2379 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2380 quiet = PRVM_G_FLOAT(OFS_PARM2);
2382 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2383 if(!VM_SEARCHLIST[handle])
2386 if(handle >= MAX_VMSEARCHES)
2388 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2389 PRVM_G_FLOAT(OFS_RETURN) = -2;
2393 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2394 PRVM_G_FLOAT(OFS_RETURN) = -1;
2396 PRVM_G_FLOAT(OFS_RETURN) = handle;
2403 void search_end(float handle)
2406 void VM_search_end(void)
2409 VM_SAFEPARMCOUNT(1, VM_search_end);
2411 handle = PRVM_G_FLOAT(OFS_PARM0);
2413 if(handle < 0 || handle >= MAX_VMSEARCHES)
2415 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2418 if(VM_SEARCHLIST[handle] == NULL)
2420 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2424 FS_FreeSearch(VM_SEARCHLIST[handle]);
2425 VM_SEARCHLIST[handle] = NULL;
2432 float search_getsize(float handle)
2435 void VM_search_getsize(void)
2438 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2440 handle = PRVM_G_FLOAT(OFS_PARM0);
2442 if(handle < 0 || handle >= MAX_VMSEARCHES)
2444 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2447 if(VM_SEARCHLIST[handle] == NULL)
2449 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2453 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2458 VM_search_getfilename
2460 string search_getfilename(float handle, float num)
2463 void VM_search_getfilename(void)
2465 int handle, filenum;
2467 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2469 handle = PRVM_G_FLOAT(OFS_PARM0);
2470 filenum = PRVM_G_FLOAT(OFS_PARM1);
2472 if(handle < 0 || handle >= MAX_VMSEARCHES)
2474 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2477 if(VM_SEARCHLIST[handle] == NULL)
2479 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2482 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2484 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2488 tmp = VM_GetTempString();
2489 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2491 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2498 string chr(float ascii)
2504 VM_SAFEPARMCOUNT(1, VM_chr);
2506 tmp = VM_GetTempString();
2507 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2510 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2513 //=============================================================================
2514 // Draw builtins (client & menu)
2520 float iscachedpic(string pic)
2523 void VM_iscachedpic(void)
2525 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2527 // drawq hasnt such a function, thus always return true
2528 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2535 string precache_pic(string pic)
2538 void VM_precache_pic(void)
2542 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2544 s = PRVM_G_STRING(OFS_PARM0);
2545 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2548 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2550 VM_CheckEmptyString (s);
2552 if(!Draw_CachePic(s))
2553 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2563 void VM_freepic(void)
2567 VM_SAFEPARMCOUNT(1,VM_freepic);
2569 s = PRVM_G_STRING(OFS_PARM0);
2572 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2574 VM_CheckEmptyString (s);
2583 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2586 void VM_drawcharacter(void)
2588 float *pos,*scale,*rgb;
2591 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2593 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2596 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2597 PRVM_G_FLOAT(OFS_RETURN) = -1;
2601 pos = PRVM_G_VECTOR(OFS_PARM0);
2602 scale = PRVM_G_VECTOR(OFS_PARM2);
2603 rgb = PRVM_G_VECTOR(OFS_PARM3);
2604 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2606 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2608 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2609 PRVM_G_FLOAT(OFS_RETURN) = -2;
2613 if(pos[2] || scale[2])
2614 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")));
2616 if(!scale[0] || !scale[1])
2618 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2619 PRVM_G_FLOAT(OFS_RETURN) = -3;
2623 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2624 PRVM_G_FLOAT(OFS_RETURN) = 1;
2631 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2634 void VM_drawstring(void)
2636 float *pos,*scale,*rgb;
2639 VM_SAFEPARMCOUNT(6,VM_drawstring);
2641 string = PRVM_G_STRING(OFS_PARM1);
2644 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2645 PRVM_G_FLOAT(OFS_RETURN) = -1;
2649 VM_CheckEmptyString(string);
2651 pos = PRVM_G_VECTOR(OFS_PARM0);
2652 scale = PRVM_G_VECTOR(OFS_PARM2);
2653 rgb = PRVM_G_VECTOR(OFS_PARM3);
2654 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2656 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2658 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2659 PRVM_G_FLOAT(OFS_RETURN) = -2;
2663 if(!scale[0] || !scale[1])
2665 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2666 PRVM_G_FLOAT(OFS_RETURN) = -3;
2670 if(pos[2] || scale[2])
2671 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")));
2673 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2674 PRVM_G_FLOAT(OFS_RETURN) = 1;
2680 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2683 void VM_drawpic(void)
2686 float *size, *pos, *rgb;
2689 VM_SAFEPARMCOUNT(6,VM_drawpic);
2691 pic = PRVM_G_STRING(OFS_PARM1);
2695 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2696 PRVM_G_FLOAT(OFS_RETURN) = -1;
2700 VM_CheckEmptyString (pic);
2702 // is pic cached ? no function yet for that
2705 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2706 PRVM_G_FLOAT(OFS_RETURN) = -4;
2710 pos = PRVM_G_VECTOR(OFS_PARM0);
2711 size = PRVM_G_VECTOR(OFS_PARM2);
2712 rgb = PRVM_G_VECTOR(OFS_PARM3);
2713 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2715 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2717 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2718 PRVM_G_FLOAT(OFS_RETURN) = -2;
2722 if(pos[2] || size[2])
2723 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")));
2725 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2726 PRVM_G_FLOAT(OFS_RETURN) = 1;
2733 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2736 void VM_drawfill(void)
2738 float *size, *pos, *rgb;
2741 VM_SAFEPARMCOUNT(5,VM_drawfill);
2744 pos = PRVM_G_VECTOR(OFS_PARM0);
2745 size = PRVM_G_VECTOR(OFS_PARM1);
2746 rgb = PRVM_G_VECTOR(OFS_PARM2);
2747 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2749 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2751 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2752 PRVM_G_FLOAT(OFS_RETURN) = -2;
2756 if(pos[2] || size[2])
2757 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")));
2759 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2760 PRVM_G_FLOAT(OFS_RETURN) = 1;
2767 drawsetcliparea(float x, float y, float width, float height)
2770 void VM_drawsetcliparea(void)
2773 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2775 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2776 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2777 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2778 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2780 DrawQ_SetClipArea(x,y,w,h);
2785 VM_drawresetcliparea
2790 void VM_drawresetcliparea(void)
2792 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2794 DrawQ_ResetClipArea();
2801 vector getimagesize(string pic)
2804 void VM_getimagesize(void)
2809 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2811 p = PRVM_G_STRING(OFS_PARM0);
2814 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2816 VM_CheckEmptyString (p);
2818 pic = Draw_CachePic (p);
2820 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2821 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2822 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2825 void VM_Cmd_Init(void)
2827 // only init the stuff for the current prog
2828 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
2833 void VM_Cmd_Reset(void)
2835 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2836 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2838 VM_Files_CloseAll();
2841 //============================================================================
2844 char *vm_sv_extensions =
2847 prvm_builtin_t vm_sv_builtins[] = {
2848 0 // to be consistent with the old vm
2851 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2853 void VM_SV_Cmd_Init(void)
2857 void VM_SV_Cmd_Reset(void)
2861 //============================================================================
2864 char *vm_cl_extensions =
2867 prvm_builtin_t vm_cl_builtins[] = {
2868 0 // to be consistent with the old vm
2871 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2873 void VM_CL_Cmd_Init(void)
2877 void VM_CL_Cmd_Reset(void)
2881 //============================================================================
2884 char *vm_m_extensions =
2891 setmousetarget(float target)
2894 void VM_M_setmousetarget(void)
2896 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2898 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2901 in_client_mouse = false;
2904 in_client_mouse = true;
2907 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2915 float getmousetarget
2918 void VM_M_getmousetarget(void)
2920 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2923 PRVM_G_FLOAT(OFS_RETURN) = 2;
2925 PRVM_G_FLOAT(OFS_RETURN) = 1;
2934 setkeydest(float dest)
2937 void VM_M_setkeydest(void)
2939 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2941 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2945 key_dest = key_game;
2949 key_dest = key_menu;
2953 // key_dest = key_message
2956 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2967 void VM_M_getkeydest(void)
2969 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2971 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2975 PRVM_G_FLOAT(OFS_RETURN) = 0;
2978 PRVM_G_FLOAT(OFS_RETURN) = 2;
2982 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2985 PRVM_G_FLOAT(OFS_RETURN) = 3;
2993 callfunction(...,string function_name)
2997 mfunction_t *PRVM_ED_FindFunction (const char *name);
2998 void VM_M_callfunction(void)
3004 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3006 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3009 PRVM_ERROR("VM_M_callfunction: null string !\n");
3011 VM_CheckEmptyString(s);
3013 func = PRVM_ED_FindFunction(s);
3016 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3017 else if (func->first_statement < 0)
3019 // negative statements are built in functions
3020 int builtinnumber = -func->first_statement;
3021 prog->xfunction->builtinsprofile++;
3022 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3023 prog->builtins[builtinnumber]();
3025 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3030 PRVM_ExecuteProgram(func - prog->functions,"");
3039 float isfunction(string function_name)
3042 mfunction_t *PRVM_ED_FindFunction (const char *name);
3043 void VM_M_isfunction(void)
3048 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3050 s = PRVM_G_STRING(OFS_PARM0);
3053 PRVM_ERROR("VM_M_isfunction: null string !\n");
3055 VM_CheckEmptyString(s);
3057 func = PRVM_ED_FindFunction(s);
3060 PRVM_G_FLOAT(OFS_RETURN) = false;
3062 PRVM_G_FLOAT(OFS_RETURN) = true;
3069 writetofile(float fhandle, entity ent)
3072 void VM_M_writetofile(void)
3077 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3079 filenum = PRVM_G_FLOAT(OFS_PARM0);
3080 if (filenum < 0 || filenum >= MAX_VMFILES)
3082 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3085 if (VM_FILES[filenum] == NULL)
3087 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3091 ent = PRVM_G_EDICT(OFS_PARM1);
3094 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3098 PRVM_ED_Write (VM_FILES[filenum], ent);
3105 vector getresolution(float number)
3108 extern unsigned short video_resolutions[][2];
3109 void VM_M_getresolution(void)
3112 VM_SAFEPARMCOUNT(1, VM_getresolution);
3114 nr = PRVM_G_FLOAT(OFS_PARM0);
3117 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3118 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3119 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3126 string keynumtostring(float keynum)
3129 void VM_M_keynumtostring(void)
3133 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3135 keynum = PRVM_G_FLOAT(OFS_PARM0);
3137 tmp = VM_GetTempString();
3139 strcpy(tmp, Key_KeynumToString(keynum));
3141 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3146 VM_M_findkeysforcommand
3148 string findkeysforcommand(string command)
3150 the returned string is an altstring
3153 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3155 void M_FindKeysForCommand(char *command, int *keys);
3156 void VM_M_findkeysforcommand(void)
3162 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3164 cmd = PRVM_G_STRING(OFS_PARM0);
3166 VM_CheckEmptyString(cmd);
3168 (ret = VM_GetTempString())[0] = 0;
3170 M_FindKeysForCommand(cmd, keys);
3172 for(i = 0; i < NUMKEYS; i++)
3173 ret = strcat(ret, va(" \'%i\'", keys[i]));
3175 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3180 VM_M_gethostcachecount
3182 float gethostcachevalue(float type)
3193 void VM_M_gethostcachevalue( void )
3196 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
3198 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3200 type = PRVM_G_FLOAT( OFS_PARM0 );
3201 if( type < 0 || type > 4 )
3202 Con_Printf( "VM_M_gethostcachevalue: bad type %i!\n", type );
3206 PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
3209 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3212 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3215 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3218 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3225 VM_M_gethostcachestring
3227 string gethostcachestring(float type, float hostnr)
3235 void VM_M_gethostcachestring(void)
3240 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3242 PRVM_G_INT(OFS_RETURN) = 0;
3244 type = PRVM_G_FLOAT(OFS_PARM0);
3246 if(type < 0 || type > 2)
3248 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3252 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3254 if(hostnr < 0 || hostnr >= hostCacheCount)
3256 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3261 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
3262 else if( type == 1 )
3263 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
3265 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
3268 prvm_builtin_t vm_m_builtins[] = {
3269 0, // to be consistent with the old vm
3270 // common builtings (mostly)
3347 VM_search_getfilename, // 77
3364 VM_WriteEntity, // 408
3380 VM_drawresetcliparea,
3381 VM_getimagesize,// 460
3390 VM_M_setmousetarget,
3391 VM_M_getmousetarget,
3396 VM_M_keynumtostring,
3397 VM_M_findkeysforcommand,// 610
3398 VM_M_gethostcachevalue,
3399 VM_M_gethostcachestring,
3400 VM_M_parseentitydata // 613
3403 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3405 void VM_M_Cmd_Init(void)
3410 void VM_M_Cmd_Reset(void)