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 float altstr_count(string)
104 string altstr_prepare(string)
105 string altstr_get(string,float)
106 string altstr_set(string altstr, float num, string set)
108 perhaps only : Menu : WriteMsg
109 ===============================
111 WriteByte(float data, float dest, float desto)
112 WriteChar(float data, float dest, float desto)
113 WriteShort(float data, float dest, float desto)
114 WriteLong(float data, float dest, float desto)
115 WriteAngle(float data, float dest, float desto)
116 WriteCoord(float data, float dest, float desto)
117 WriteString(string data, float dest, float desto)
118 WriteEntity(entity data, float dest, float desto)
120 Client & Menu : draw functions & video functions
121 ===================================================
123 float iscachedpic(string pic)
124 string precache_pic(string pic)
126 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
127 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
128 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
129 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
130 drawsetcliparea(float x, float y, float width, float height)
132 vector getimagesize(string pic)
134 float cin_open(string file, string name)
135 void cin_close(string name)
136 void cin_setstate(string name, float type)
137 float cin_getstate(string name)
138 void cin_restart(string name)
140 ==============================================================================
144 setkeydest(float dest)
146 setmousetarget(float target)
147 float getmousetarget()
149 callfunction(...,string function_name)
150 writetofile(float fhandle, entity ent)
151 float isfunction(string function_name)
152 vector getresolution(float number)
153 string keynumtostring(float keynum)
154 string findkeysforcommand(string command)
155 float gethostcachestat(float type)
156 string gethostcachestring(float fld, float hostnr)
158 parseentitydata(entity ent, string data)
160 float stringtokeynum(string key)
163 sethostcachemaskstring(float fld, string str)
164 sethostcachemasknumber(float fld, float num, float op)
166 sethostcachesort(float field, float descending)
168 float gethostcachenumber(float fld, float hostnr)
171 #include "quakedef.h"
172 #include "progdefs.h"
174 #include "clprogdefs.h"
175 #include "mprogdefs.h"
177 #include "cl_video.h"
179 //============================================================================
180 // nice helper macros
182 #ifndef VM_NOPARMCHECK
183 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
185 #define VM_SAFEPARMCOUNT(p,f)
188 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
190 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
192 #define e10 0,0,0,0,0,0,0,0,0,0
193 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
194 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
196 //============================================================================
199 // string zone mempool
200 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
202 // temp string handling
203 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
204 #define VM_STRINGTEMP_BUFFERS 16
205 #define VM_STRINGTEMP_LENGTH 4096
206 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
207 static int vm_string_tempindex = 0;
210 #define MAX_VMFILES 256
211 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
212 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
214 qfile_t *vm_files[MAX_PRVMFILES];
216 // qc fs search handling
217 #define MAX_VMSEARCHES 128
218 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
219 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
221 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
223 static char *VM_GetTempString(void)
226 s = vm_string_temp[vm_string_tempindex];
227 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
231 void VM_CheckEmptyString (char *s)
234 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
237 //============================================================================
240 void VM_VarString(int first, char *out, int outlength)
246 outend = out + outlength - 1;
247 for (i = first;i < prog->argc && out < outend;i++)
249 s = PRVM_G_STRING((OFS_PARM0+i*3));
250 while (out < outend && *s)
260 returns true if the extension is supported by the server
262 checkextension(extensionname)
266 // kind of helper function
267 static qboolean checkextension(char *name)
273 for (e = prog->extensionstring;*e;e++)
280 while (*e && *e != ' ')
282 if (e - start == len)
283 if (!strncasecmp(start, name, len))
291 void VM_checkextension (void)
293 VM_SAFEPARMCOUNT(1,VM_checkextension);
295 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
302 This is a TERMINAL error, which will kill off the entire prog.
311 char string[VM_STRINGTEMP_LENGTH];
313 VM_VarString(0, string, sizeof(string));
314 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
317 ed = PRVM_G_EDICT(prog->self->ofs);
321 PRVM_ERROR ("%s: Program error", PRVM_NAME);
328 Dumps out self, then an error message. The program is aborted and self is
329 removed, but the level can continue.
334 void VM_objerror (void)
337 char string[VM_STRINGTEMP_LENGTH];
339 VM_VarString(0, string, sizeof(string));
340 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
343 ed = PRVM_G_EDICT (prog->self->ofs);
349 // objerror has to display the object fields -> else call
350 PRVM_ERROR ("VM_objecterror: self not defined !\n");
355 VM_print (actually used only by client and menu)
364 char string[VM_STRINGTEMP_LENGTH];
366 VM_VarString(0, string, sizeof(string));
374 broadcast print to everyone on server
379 void VM_bprint (void)
381 char string[VM_STRINGTEMP_LENGTH];
385 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
389 VM_VarString(0, string, sizeof(string));
390 SV_BroadcastPrint(string);
395 VM_sprint (menu & client but only if server.active == true)
397 single print to a specific client
399 sprint(float clientnum,...[string])
402 void VM_sprint (void)
406 char string[VM_STRINGTEMP_LENGTH];
408 //find client for this entity
409 clientnum = PRVM_G_FLOAT(OFS_PARM0);
410 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
412 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
416 client = svs.clients + clientnum;
417 VM_VarString(1, string, sizeof(string));
418 MSG_WriteChar(&client->message,svc_print);
419 MSG_WriteString(&client->message, string);
426 single print to the screen
428 centerprint(clientent, value)
431 void VM_centerprint (void)
433 char string[VM_STRINGTEMP_LENGTH];
435 VM_VarString(0, string, sizeof(string));
436 SCR_CenterPrint(string);
443 vector normalize(vector)
446 void VM_normalize (void)
452 VM_SAFEPARMCOUNT(1,VM_normalize);
454 value1 = PRVM_G_VECTOR(OFS_PARM0);
456 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
460 newvalue[0] = newvalue[1] = newvalue[2] = 0;
464 newvalue[0] = value1[0] * new;
465 newvalue[1] = value1[1] * new;
466 newvalue[2] = value1[2] * new;
469 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
484 VM_SAFEPARMCOUNT(1,VM_vlen);
486 value1 = PRVM_G_VECTOR(OFS_PARM0);
488 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
491 PRVM_G_FLOAT(OFS_RETURN) = new;
498 float vectoyaw(vector)
501 void VM_vectoyaw (void)
506 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
508 value1 = PRVM_G_VECTOR(OFS_PARM0);
510 if (value1[1] == 0 && value1[0] == 0)
514 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
519 PRVM_G_FLOAT(OFS_RETURN) = yaw;
527 vector vectoangles(vector)
530 void VM_vectoangles (void)
536 VM_SAFEPARMCOUNT(1,VM_vectoangles);
538 value1 = PRVM_G_VECTOR(OFS_PARM0);
540 if (value1[1] == 0 && value1[0] == 0)
550 // LordHavoc: optimized a bit
553 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
557 else if (value1[1] > 0)
562 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
563 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
568 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
569 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
570 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
577 Returns a number from 0<= num < 1
582 void VM_random (void)
584 VM_SAFEPARMCOUNT(0,VM_random);
586 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
593 Each entity can have eight independant sound sources, like voice,
596 Channel 0 is an auto-allocate channel, the others override anything
597 already running on that entity/channel pair.
599 An attenuation of 0 will play full volume everywhere in the level.
600 Larger attenuations will drop off.
613 entity = G_EDICT(OFS_PARM0);
614 channel = G_FLOAT(OFS_PARM1);
615 sample = G_STRING(OFS_PARM2);
616 volume = G_FLOAT(OFS_PARM3) * 255;
617 attenuation = G_FLOAT(OFS_PARM4);
619 if (volume < 0 || volume > 255)
620 Host_Error ("SV_StartSound: volume = %i", volume);
622 if (attenuation < 0 || attenuation > 4)
623 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
625 if (channel < 0 || channel > 7)
626 Host_Error ("SV_StartSound: channel = %i", channel);
628 SV_StartSound (entity, channel, sample, volume, attenuation);
636 localsound(string sample)
639 void VM_localsound(void)
643 VM_SAFEPARMCOUNT(1,VM_localsound);
645 s = PRVM_G_STRING(OFS_PARM0);
647 if(!S_LocalSound (s))
649 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
650 PRVM_G_FLOAT(OFS_RETURN) = -4;
654 PRVM_G_FLOAT(OFS_RETURN) = 1;
666 PRVM_ERROR ("%s: break statement", PRVM_NAME);
669 //============================================================================
675 Sends text over to the client's execution buffer
677 [localcmd (string) or]
681 void VM_localcmd (void)
683 VM_SAFEPARMCOUNT(1,VM_localcmd);
685 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
697 VM_SAFEPARMCOUNT(1,VM_cvar);
699 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
706 const string str_cvar (string)
709 void VM_str_cvar(void)
712 const char *cvar_string;
713 VM_SAFEPARMCOUNT(1,VM_str_cvar);
715 name = PRVM_G_STRING(OFS_PARM0);
718 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
720 VM_CheckEmptyString(name);
722 out = VM_GetTempString();
724 cvar_string = Cvar_VariableString(name);
726 strcpy(out, cvar_string);
728 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
735 void cvar_set (string,string)
738 void VM_cvar_set (void)
740 VM_SAFEPARMCOUNT(2,VM_cvar_set);
742 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
752 void VM_dprint (void)
754 char string[VM_STRINGTEMP_LENGTH];
755 if (developer.integer)
757 VM_VarString(0, string, sizeof(string));
758 Con_Printf("%s: %s", PRVM_NAME, string);
775 VM_SAFEPARMCOUNT(1, VM_ftos);
777 v = PRVM_G_FLOAT(OFS_PARM0);
779 s = VM_GetTempString();
780 if ((float)((int)v) == v)
781 sprintf(s, "%i", (int)v);
784 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
799 VM_SAFEPARMCOUNT(1,VM_fabs);
801 v = PRVM_G_FLOAT(OFS_PARM0);
802 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
817 VM_SAFEPARMCOUNT(1,VM_vtos);
819 s = VM_GetTempString();
820 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]);
821 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
836 VM_SAFEPARMCOUNT(1, VM_etos);
838 s = VM_GetTempString();
839 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
840 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
847 float stof(...[string])
852 char string[VM_STRINGTEMP_LENGTH];
853 VM_VarString(0, string, sizeof(string));
854 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
858 ========================
862 ========================
866 VM_SAFEPARMCOUNT(1, VM_itof);
867 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
871 ========================
875 ========================
880 VM_SAFEPARMCOUNT(1, VM_ftoi);
882 ent = PRVM_G_FLOAT(OFS_PARM0);
883 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
884 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
886 PRVM_G_INT(OFS_RETURN) = ent;
900 prog->xfunction->builtinsprofile += 20;
901 ed = PRVM_ED_Alloc();
913 void VM_remove (void)
916 prog->xfunction->builtinsprofile += 20;
918 VM_SAFEPARMCOUNT(1, VM_remove);
920 ed = PRVM_G_EDICT(OFS_PARM0);
921 // if (ed == prog->edicts)
922 // PRVM_ERROR ("remove: tried to remove world\n");
923 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
924 // Host_Error("remove: tried to remove a client\n");
932 entity find(entity start, .string field, string match)
943 VM_SAFEPARMCOUNT(3,VM_find);
945 e = PRVM_G_EDICTNUM(OFS_PARM0);
946 f = PRVM_G_INT(OFS_PARM1);
947 s = PRVM_G_STRING(OFS_PARM2);
951 // return reserved edict 0 (could be used for whatever the prog wants)
952 VM_RETURN_EDICT(prog->edicts);
956 for (e++ ; e < prog->num_edicts ; e++)
958 prog->xfunction->builtinsprofile++;
959 ed = PRVM_EDICT_NUM(e);
962 t = PRVM_E_STRING(ed,f);
972 VM_RETURN_EDICT(prog->edicts);
979 entity findfloat(entity start, .float field, float match)
980 entity findentity(entity start, .entity field, entity match)
983 // LordHavoc: added this for searching float, int, and entity reference fields
984 void VM_findfloat (void)
991 VM_SAFEPARMCOUNT(3,VM_findfloat);
993 e = PRVM_G_EDICTNUM(OFS_PARM0);
994 f = PRVM_G_INT(OFS_PARM1);
995 s = PRVM_G_FLOAT(OFS_PARM2);
997 for (e++ ; e < prog->num_edicts ; e++)
999 prog->xfunction->builtinsprofile++;
1000 ed = PRVM_EDICT_NUM(e);
1003 if (PRVM_E_FLOAT(ed,f) == s)
1005 VM_RETURN_EDICT(ed);
1010 VM_RETURN_EDICT(prog->edicts);
1017 entity findchain(.string field, string match)
1020 int PRVM_ED_FindFieldOffset(const char *field);
1021 // chained search for strings in entity fields
1022 // entity(.string field, string match) findchain = #402;
1023 void VM_findchain (void)
1029 prvm_edict_t *ent, *chain;
1031 VM_SAFEPARMCOUNT(2,VM_findchain);
1033 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1034 if(!prog->flag & PRVM_FE_CHAIN)
1035 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1037 chain_of = PRVM_ED_FindFieldOffset ("chain");
1039 chain = prog->edicts;
1041 f = PRVM_G_INT(OFS_PARM0);
1042 s = PRVM_G_STRING(OFS_PARM1);
1045 VM_RETURN_EDICT(prog->edicts);
1049 ent = PRVM_NEXT_EDICT(prog->edicts);
1050 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1052 prog->xfunction->builtinsprofile++;
1055 t = PRVM_E_STRING(ent,f);
1061 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1065 VM_RETURN_EDICT(chain);
1072 entity findchainfloat(.string field, float match)
1073 entity findchainentity(.string field, entity match)
1076 // LordHavoc: chained search for float, int, and entity reference fields
1077 // entity(.string field, float match) findchainfloat = #403;
1078 void VM_findchainfloat (void)
1084 prvm_edict_t *ent, *chain;
1086 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1088 if(!prog->flag & PRVM_FE_CHAIN)
1089 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1091 chain_of = PRVM_ED_FindFieldOffset ("chain");
1093 chain = (prvm_edict_t *)prog->edicts;
1095 f = PRVM_G_INT(OFS_PARM0);
1096 s = PRVM_G_FLOAT(OFS_PARM1);
1098 ent = PRVM_NEXT_EDICT(prog->edicts);
1099 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1101 prog->xfunction->builtinsprofile++;
1104 if (PRVM_E_FLOAT(ent,f) != s)
1107 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1111 VM_RETURN_EDICT(chain);
1118 string precache_file(string)
1121 void VM_precache_file (void)
1122 { // precache_file is only used to copy files with qcc, it does nothing
1123 VM_SAFEPARMCOUNT(1,VM_precache_file);
1125 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1132 used instead of the other VM_precache_* functions in the builtin list
1136 void VM_precache_error (void)
1138 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1145 string precache_sound (string sample)
1148 void VM_precache_sound (void)
1152 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1154 s = PRVM_G_STRING(OFS_PARM0);
1155 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1156 VM_CheckEmptyString (s);
1158 if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
1159 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1169 void VM_coredump (void)
1171 VM_SAFEPARMCOUNT(0,VM_coredump);
1173 Cbuf_AddText("prvm_edicts ");
1174 Cbuf_AddText(PRVM_NAME);
1185 void PRVM_StackTrace(void);
1186 void VM_stackdump (void)
1188 VM_SAFEPARMCOUNT(0, VM_stackdump);
1203 VM_SAFEPARMCOUNT(0, VM_crash);
1205 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1215 void VM_traceon (void)
1217 VM_SAFEPARMCOUNT(0,VM_traceon);
1229 void VM_traceoff (void)
1231 VM_SAFEPARMCOUNT(0,VM_traceoff);
1233 prog->trace = false;
1243 void VM_eprint (void)
1245 VM_SAFEPARMCOUNT(1,VM_eprint);
1247 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1261 VM_SAFEPARMCOUNT(1,VM_rint);
1263 f = PRVM_G_FLOAT(OFS_PARM0);
1265 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1267 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1277 void VM_floor (void)
1279 VM_SAFEPARMCOUNT(1,VM_floor);
1281 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1293 VM_SAFEPARMCOUNT(1,VM_ceil);
1295 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1303 entity nextent(entity)
1306 void VM_nextent (void)
1311 i = PRVM_G_EDICTNUM(OFS_PARM0);
1314 prog->xfunction->builtinsprofile++;
1316 if (i == prog->num_edicts)
1318 VM_RETURN_EDICT(prog->edicts);
1321 ent = PRVM_EDICT_NUM(i);
1322 if (!ent->p.e->free)
1324 VM_RETURN_EDICT(ent);
1331 ===============================================================================
1334 used only for client and menu
1335 severs uses VM_SV_...
1337 Write*(* data, float type, float to)
1339 ===============================================================================
1342 #define MSG_BROADCAST 0 // unreliable to all
1343 #define MSG_ONE 1 // reliable to one (msg_entity)
1344 #define MSG_ALL 2 // reliable to all
1345 #define MSG_INIT 3 // write to the init string
1347 sizebuf_t *VM_WriteDest (void)
1353 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1355 dest = G_FLOAT(OFS_PARM1);
1359 return &sv.datagram;
1362 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1363 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1364 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1366 return &svs.clients[destclient].message;
1369 return &sv.reliable_datagram;
1375 PRVM_ERROR ("WriteDest: bad destination");
1382 void VM_WriteByte (void)
1384 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1387 void VM_WriteChar (void)
1389 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1392 void VM_WriteShort (void)
1394 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1397 void VM_WriteLong (void)
1399 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1402 void VM_WriteAngle (void)
1404 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1407 void VM_WriteCoord (void)
1409 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1412 void VM_WriteString (void)
1414 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1417 void VM_WriteEntity (void)
1419 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1422 //=============================================================================
1429 changelevel(string map)
1432 void VM_changelevel (void)
1436 VM_SAFEPARMCOUNT(1, VM_changelevel);
1440 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1444 // make sure we don't issue two changelevels
1445 if (svs.changelevel_issued)
1447 svs.changelevel_issued = true;
1449 s = G_STRING(OFS_PARM0);
1450 Cbuf_AddText (va("changelevel %s\n",s));
1462 VM_SAFEPARMCOUNT(1,VM_sin);
1463 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1474 VM_SAFEPARMCOUNT(1,VM_cos);
1475 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1487 VM_SAFEPARMCOUNT(1,VM_sqrt);
1488 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1495 Returns a vector of length < 1 and > 0
1500 void VM_randomvec (void)
1505 VM_SAFEPARMCOUNT(0, VM_randomvec);
1510 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1511 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1512 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1514 while (DotProduct(temp, temp) >= 1);
1515 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1518 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1519 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1520 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1521 // length returned always > 0
1522 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1523 VectorScale(temp,length, temp);*/
1524 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1527 //=============================================================================
1533 float registercvar (string name, string value, float flags)
1536 void VM_registercvar (void)
1541 VM_SAFEPARMCOUNT(3,VM_registercvar);
1543 name = PRVM_G_STRING(OFS_PARM0);
1544 value = PRVM_G_STRING(OFS_PARM1);
1545 flags = PRVM_G_FLOAT(OFS_PARM2);
1546 PRVM_G_FLOAT(OFS_RETURN) = 0;
1548 if(flags > CVAR_MAXFLAGSVAL)
1551 // first check to see if it has already been defined
1552 if (Cvar_FindVar (name))
1555 // check for overlap with a command
1556 if (Cmd_Exists (name))
1558 Con_Printf("VM_registercvar: %s is a command\n", name);
1562 Cvar_Get(name, value, flags);
1564 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1571 returns the minimum of two supplied floats
1573 float min(float a, float b, ...[float])
1578 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1579 if (prog->argc == 2)
1580 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1581 else if (prog->argc >= 3)
1584 float f = PRVM_G_FLOAT(OFS_PARM0);
1585 for (i = 1;i < prog->argc;i++)
1586 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1587 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1588 PRVM_G_FLOAT(OFS_RETURN) = f;
1591 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1598 returns the maximum of two supplied floats
1600 float max(float a, float b, ...[float])
1605 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1606 if (prog->argc == 2)
1607 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1608 else if (prog->argc >= 3)
1611 float f = PRVM_G_FLOAT(OFS_PARM0);
1612 for (i = 1;i < prog->argc;i++)
1613 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1614 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1615 PRVM_G_FLOAT(OFS_RETURN) = f;
1618 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1625 returns number bounded by supplied range
1627 float bound(float min, float value, float max)
1630 void VM_bound (void)
1632 VM_SAFEPARMCOUNT(3,VM_bound);
1633 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1640 returns a raised to power b
1642 float pow(float a, float b)
1647 VM_SAFEPARMCOUNT(2,VM_pow);
1648 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1655 copies data from one entity to another
1657 copyentity(entity src, entity dst)
1660 void VM_copyentity (void)
1662 prvm_edict_t *in, *out;
1663 VM_SAFEPARMCOUNT(2,VM_copyentity);
1664 in = PRVM_G_EDICT(OFS_PARM0);
1665 out = PRVM_G_EDICT(OFS_PARM1);
1666 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1673 sets the color of a client and broadcasts the update to all connected clients
1675 setcolor(clientent, value)
1678 /*void PF_setcolor (void)
1684 entnum = G_EDICTNUM(OFS_PARM0);
1685 i = G_FLOAT(OFS_PARM1);
1687 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1689 Con_Print("tried to setcolor a non-client\n");
1693 client = svs.clients + entnum-1;
1694 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1697 client->old_colors = i;
1698 client->edict->v->team = (i & 15) + 1;
1700 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1701 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1702 MSG_WriteByte (&sv.reliable_datagram, i);
1705 void VM_Files_Init(void)
1707 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1710 void VM_Files_CloseAll(void)
1713 for (i = 0;i < MAX_VMFILES;i++)
1716 FS_Close(VM_FILES[i]);
1717 //VM_FILES[i] = NULL;
1719 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1726 float fopen(string filename, float mode)
1729 // float(string filename, float mode) fopen = #110;
1730 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1731 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1735 char *modestring, *filename;
1737 VM_SAFEPARMCOUNT(2,VM_fopen);
1739 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1740 if (VM_FILES[filenum] == NULL)
1742 if (filenum >= MAX_VMFILES)
1744 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1745 PRVM_G_FLOAT(OFS_RETURN) = -2;
1748 mode = PRVM_G_FLOAT(OFS_PARM1);
1751 case 0: // FILE_READ
1754 case 1: // FILE_APPEND
1757 case 2: // FILE_WRITE
1761 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1762 PRVM_G_FLOAT(OFS_RETURN) = -3;
1765 filename = PRVM_G_STRING(OFS_PARM0);
1766 // .. is parent directory on many platforms
1767 // / is parent directory on Amiga
1768 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1769 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1770 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1772 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1773 PRVM_G_FLOAT(OFS_RETURN) = -4;
1776 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1777 if (VM_FILES[filenum] == NULL && mode == 0)
1778 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1780 if (VM_FILES[filenum] == NULL)
1781 PRVM_G_FLOAT(OFS_RETURN) = -1;
1783 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1790 fclose(float fhandle)
1793 //void(float fhandle) fclose = #111; // closes a file
1794 void VM_fclose(void)
1798 VM_SAFEPARMCOUNT(1,VM_fclose);
1800 filenum = PRVM_G_FLOAT(OFS_PARM0);
1801 if (filenum < 0 || filenum >= MAX_VMFILES)
1803 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1806 if (VM_FILES[filenum] == NULL)
1808 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1811 FS_Close(VM_FILES[filenum]);
1812 VM_FILES[filenum] = NULL;
1819 string fgets(float fhandle)
1822 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1826 static char string[VM_STRINGTEMP_LENGTH];
1829 VM_SAFEPARMCOUNT(1,VM_fgets);
1831 filenum = PRVM_G_FLOAT(OFS_PARM0);
1832 if (filenum < 0 || filenum >= MAX_VMFILES)
1834 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1837 if (VM_FILES[filenum] == NULL)
1839 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1845 c = FS_Getc(VM_FILES[filenum]);
1846 if (c == '\r' || c == '\n' || c < 0)
1848 if (end < VM_STRINGTEMP_LENGTH - 1)
1852 // remove \n following \r
1854 c = FS_Getc(VM_FILES[filenum]);
1855 if (developer.integer >= 3)
1856 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1858 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1860 PRVM_G_INT(OFS_RETURN) = 0;
1867 fputs(float fhandle, string s)
1870 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1874 char string[VM_STRINGTEMP_LENGTH];
1877 VM_SAFEPARMCOUNT(2,VM_fputs);
1879 filenum = PRVM_G_FLOAT(OFS_PARM0);
1880 if (filenum < 0 || filenum >= MAX_VMFILES)
1882 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1885 if (VM_FILES[filenum] == NULL)
1887 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1890 VM_VarString(1, string, sizeof(string));
1891 if ((stringlength = strlen(string)))
1892 FS_Write(VM_FILES[filenum], string, stringlength);
1893 if (developer.integer)
1894 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1901 float strlen(string s)
1904 //float(string s) strlen = #114; // returns how many characters are in a string
1905 void VM_strlen(void)
1909 VM_SAFEPARMCOUNT(1,VM_strlen);
1911 s = PRVM_G_STRING(OFS_PARM0);
1913 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1915 PRVM_G_FLOAT(OFS_RETURN) = 0;
1922 string strcat(string,string,...[string])
1925 //string(string s1, string s2) strcat = #115;
1926 // concatenates two strings (for example "abc", "def" would return "abcdef")
1927 // and returns as a tempstring
1928 void VM_strcat(void)
1933 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1935 s = VM_GetTempString();
1936 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1937 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1944 string substring(string s, float start, float length)
1947 // string(string s, float start, float length) substring = #116;
1948 // returns a section of a string as a tempstring
1949 void VM_substring(void)
1951 int i, start, length;
1954 VM_SAFEPARMCOUNT(3,VM_substring);
1956 string = VM_GetTempString();
1957 s = PRVM_G_STRING(OFS_PARM0);
1958 start = PRVM_G_FLOAT(OFS_PARM1);
1959 length = PRVM_G_FLOAT(OFS_PARM2);
1962 for (i = 0;i < start && *s;i++, s++);
1963 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1966 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1973 vector stov(string s)
1976 //vector(string s) stov = #117; // returns vector value from a string
1979 char string[VM_STRINGTEMP_LENGTH];
1981 VM_SAFEPARMCOUNT(1,VM_stov);
1983 VM_VarString(0, string, sizeof(string));
1984 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1991 string strzone(string s)
1994 //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)
1995 void VM_strzone(void)
1999 VM_SAFEPARMCOUNT(1,VM_strzone);
2001 in = PRVM_G_STRING(OFS_PARM0);
2002 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
2004 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2014 //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!!!)
2015 void VM_strunzone(void)
2018 VM_SAFEPARMCOUNT(1,VM_strunzone);
2020 str = PRVM_G_STRING(OFS_PARM0);
2021 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2022 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2029 VM_command (used by client and menu)
2031 clientcommand(float client, string s) (for client and menu)
2034 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2035 //this function originally written by KrimZon, made shorter by LordHavoc
2036 void VM_clcommand (void)
2038 client_t *temp_client;
2041 VM_SAFEPARMCOUNT(2,VM_clcommand);
2043 i = PRVM_G_FLOAT(OFS_PARM0);
2044 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2046 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2050 temp_client = host_client;
2051 host_client = svs.clients + i;
2052 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2053 host_client = temp_client;
2061 float tokenize(string s)
2064 //float(string s) tokenize = #441;
2065 // takes apart a string into individal words (access them with argv), returns how many
2066 // this function originally written by KrimZon, made shorter by LordHavoc
2067 static char **tokens = NULL;
2068 static int max_tokens, num_tokens = 0;
2069 void VM_tokenize (void)
2074 VM_SAFEPARMCOUNT(1,VM_tokenize);
2076 str = PRVM_G_STRING(OFS_PARM0);
2081 for (i=0;i<num_tokens;i++)
2087 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2088 max_tokens = strlen(str);
2090 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2092 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2093 strcpy(tokens[num_tokens], com_token);
2096 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2103 string argv(float n)
2106 //string(float n) argv = #442;
2107 // returns a word from the tokenized string (returns nothing for an invalid index)
2108 // this function originally written by KrimZon, made shorter by LordHavoc
2113 VM_SAFEPARMCOUNT(1,VM_argv);
2115 token_num = PRVM_G_FLOAT(OFS_PARM0);
2116 if (token_num >= 0 && token_num < num_tokens)
2117 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2119 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2123 //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)
2124 void PF_setattachment (void)
2126 edict_t *e = G_EDICT(OFS_PARM0);
2127 edict_t *tagentity = G_EDICT(OFS_PARM1);
2128 char *tagname = G_STRING(OFS_PARM2);
2133 if (tagentity == NULL)
2134 tagentity = sv.edicts;
2136 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2138 v->edict = EDICT_TO_PROG(tagentity);
2140 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2143 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2145 modelindex = (int)tagentity->v->modelindex;
2146 if (modelindex >= 0 && modelindex < MAX_MODELS)
2148 model = sv.models[modelindex];
2149 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2150 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2151 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2153 // FIXME: use a model function to get tag info (need to handle skeletal)
2154 if (v->_float == 0 && model->alias.aliasnum_tags)
2155 for (i = 0;i < model->alias.aliasnum_tags;i++)
2156 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2159 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);
2162 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));
2173 void VM_isserver(void)
2175 VM_SAFEPARMCOUNT(0,VM_serverstate);
2177 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2187 void VM_clientcount(void)
2189 VM_SAFEPARMCOUNT(0,VM_clientcount);
2191 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2201 void VM_clientstate(void)
2203 VM_SAFEPARMCOUNT(0,VM_clientstate);
2205 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2212 float getostype(void)
2214 */ // not used at the moment -> not included in the common list
2215 void VM_getostype(void)
2217 VM_SAFEPARMCOUNT(0,VM_getostype);
2222 OS_MAC - not supported
2226 PRVM_G_FLOAT(OFS_RETURN) = 0;
2228 PRVM_G_FLOAT(OFS_RETURN) = 2;
2230 PRVM_G_FLOAT(OFS_RETURN) = 1;
2238 vector getmousepos()
2241 void VM_getmousepos(void)
2244 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2246 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2247 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2248 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2258 void VM_gettime(void)
2260 VM_SAFEPARMCOUNT(0,VM_gettime);
2262 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2269 loadfromdata(string data)
2272 void VM_loadfromdata(void)
2274 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2276 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2280 ========================
2281 VM_M_parseentitydata
2283 parseentitydata(entity ent, string data)
2284 ========================
2286 void VM_M_parseentitydata(void)
2291 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2293 // get edict and test it
2294 ent = PRVM_G_EDICT(OFS_PARM0);
2296 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2298 data = PRVM_G_STRING(OFS_PARM1);
2300 // parse the opening brace
2301 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2302 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2304 PRVM_ED_ParseEdict (data, ent);
2311 loadfromfile(string file)
2314 void VM_loadfromfile(void)
2319 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2321 filename = PRVM_G_STRING(OFS_PARM0);
2322 // .. is parent directory on many platforms
2323 // / is parent directory on Amiga
2324 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2325 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2326 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2328 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2329 PRVM_G_FLOAT(OFS_RETURN) = -4;
2333 // not conform with VM_fopen
2334 data = FS_LoadFile(filename, tempmempool, false);
2336 PRVM_G_FLOAT(OFS_RETURN) = -1;
2338 PRVM_ED_LoadFromFile(data);
2349 float mod(float val, float m)
2352 void VM_modulo(void)
2355 VM_SAFEPARMCOUNT(2,VM_module);
2357 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2358 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2360 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2363 void VM_Search_Init(void)
2365 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2368 void VM_Search_Reset(void)
2371 // reset the fssearch list
2372 for(i = 0; i < MAX_VMSEARCHES; i++)
2373 if(VM_SEARCHLIST[i])
2374 FS_FreeSearch(VM_SEARCHLIST[i]);
2375 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2382 float search_begin(string pattern, float caseinsensitive, float quiet)
2385 void VM_search_begin(void)
2389 int caseinsens, quiet;
2391 VM_SAFEPARMCOUNT(3, VM_search_begin);
2393 pattern = PRVM_G_STRING(OFS_PARM0);
2395 VM_CheckEmptyString(pattern);
2397 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2398 quiet = PRVM_G_FLOAT(OFS_PARM2);
2400 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2401 if(!VM_SEARCHLIST[handle])
2404 if(handle >= MAX_VMSEARCHES)
2406 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2407 PRVM_G_FLOAT(OFS_RETURN) = -2;
2411 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2412 PRVM_G_FLOAT(OFS_RETURN) = -1;
2414 PRVM_G_FLOAT(OFS_RETURN) = handle;
2421 void search_end(float handle)
2424 void VM_search_end(void)
2427 VM_SAFEPARMCOUNT(1, VM_search_end);
2429 handle = PRVM_G_FLOAT(OFS_PARM0);
2431 if(handle < 0 || handle >= MAX_VMSEARCHES)
2433 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2436 if(VM_SEARCHLIST[handle] == NULL)
2438 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2442 FS_FreeSearch(VM_SEARCHLIST[handle]);
2443 VM_SEARCHLIST[handle] = NULL;
2450 float search_getsize(float handle)
2453 void VM_search_getsize(void)
2456 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2458 handle = PRVM_G_FLOAT(OFS_PARM0);
2460 if(handle < 0 || handle >= MAX_VMSEARCHES)
2462 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2465 if(VM_SEARCHLIST[handle] == NULL)
2467 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2471 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2476 VM_search_getfilename
2478 string search_getfilename(float handle, float num)
2481 void VM_search_getfilename(void)
2483 int handle, filenum;
2485 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2487 handle = PRVM_G_FLOAT(OFS_PARM0);
2488 filenum = PRVM_G_FLOAT(OFS_PARM1);
2490 if(handle < 0 || handle >= MAX_VMSEARCHES)
2492 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2495 if(VM_SEARCHLIST[handle] == NULL)
2497 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2500 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2502 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2506 tmp = VM_GetTempString();
2507 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2509 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2516 string chr(float ascii)
2522 VM_SAFEPARMCOUNT(1, VM_chr);
2524 tmp = VM_GetTempString();
2525 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2528 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2531 //=============================================================================
2532 // Draw builtins (client & menu)
2538 float iscachedpic(string pic)
2541 void VM_iscachedpic(void)
2543 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2545 // drawq hasnt such a function, thus always return true
2546 PRVM_G_FLOAT(OFS_RETURN) = false;
2553 string precache_pic(string pic)
2556 void VM_precache_pic(void)
2560 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2562 s = PRVM_G_STRING(OFS_PARM0);
2563 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2566 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2568 VM_CheckEmptyString (s);
2570 if(!Draw_CachePic(s))
2571 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2581 void VM_freepic(void)
2585 VM_SAFEPARMCOUNT(1,VM_freepic);
2587 s = PRVM_G_STRING(OFS_PARM0);
2590 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2592 VM_CheckEmptyString (s);
2601 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2604 void VM_drawcharacter(void)
2606 float *pos,*scale,*rgb;
2609 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2611 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2614 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2615 PRVM_G_FLOAT(OFS_RETURN) = -1;
2619 pos = PRVM_G_VECTOR(OFS_PARM0);
2620 scale = PRVM_G_VECTOR(OFS_PARM2);
2621 rgb = PRVM_G_VECTOR(OFS_PARM3);
2622 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2624 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2626 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2627 PRVM_G_FLOAT(OFS_RETURN) = -2;
2631 if(pos[2] || scale[2])
2632 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")));
2634 if(!scale[0] || !scale[1])
2636 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2637 PRVM_G_FLOAT(OFS_RETURN) = -3;
2641 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2642 PRVM_G_FLOAT(OFS_RETURN) = 1;
2649 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2652 void VM_drawstring(void)
2654 float *pos,*scale,*rgb;
2657 VM_SAFEPARMCOUNT(6,VM_drawstring);
2659 string = PRVM_G_STRING(OFS_PARM1);
2662 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2663 PRVM_G_FLOAT(OFS_RETURN) = -1;
2667 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2669 pos = PRVM_G_VECTOR(OFS_PARM0);
2670 scale = PRVM_G_VECTOR(OFS_PARM2);
2671 rgb = PRVM_G_VECTOR(OFS_PARM3);
2672 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2674 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2676 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2677 PRVM_G_FLOAT(OFS_RETURN) = -2;
2681 if(!scale[0] || !scale[1])
2683 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2684 PRVM_G_FLOAT(OFS_RETURN) = -3;
2688 if(pos[2] || scale[2])
2689 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")));
2691 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2692 PRVM_G_FLOAT(OFS_RETURN) = 1;
2698 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2701 void VM_drawpic(void)
2704 float *size, *pos, *rgb;
2707 VM_SAFEPARMCOUNT(6,VM_drawpic);
2709 pic = PRVM_G_STRING(OFS_PARM1);
2713 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2714 PRVM_G_FLOAT(OFS_RETURN) = -1;
2718 VM_CheckEmptyString (pic);
2720 // is pic cached ? no function yet for that
2723 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2724 PRVM_G_FLOAT(OFS_RETURN) = -4;
2728 pos = PRVM_G_VECTOR(OFS_PARM0);
2729 size = PRVM_G_VECTOR(OFS_PARM2);
2730 rgb = PRVM_G_VECTOR(OFS_PARM3);
2731 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2733 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2735 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2736 PRVM_G_FLOAT(OFS_RETURN) = -2;
2740 if(pos[2] || size[2])
2741 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")));
2743 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2744 PRVM_G_FLOAT(OFS_RETURN) = 1;
2751 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2754 void VM_drawfill(void)
2756 float *size, *pos, *rgb;
2759 VM_SAFEPARMCOUNT(5,VM_drawfill);
2762 pos = PRVM_G_VECTOR(OFS_PARM0);
2763 size = PRVM_G_VECTOR(OFS_PARM1);
2764 rgb = PRVM_G_VECTOR(OFS_PARM2);
2765 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2767 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2769 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2770 PRVM_G_FLOAT(OFS_RETURN) = -2;
2774 if(pos[2] || size[2])
2775 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")));
2777 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2778 PRVM_G_FLOAT(OFS_RETURN) = 1;
2785 drawsetcliparea(float x, float y, float width, float height)
2788 void VM_drawsetcliparea(void)
2791 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2793 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2794 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2795 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2796 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2798 DrawQ_SetClipArea(x, y, w, h);
2803 VM_drawresetcliparea
2808 void VM_drawresetcliparea(void)
2810 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2812 DrawQ_ResetClipArea();
2819 vector getimagesize(string pic)
2822 void VM_getimagesize(void)
2827 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2829 p = PRVM_G_STRING(OFS_PARM0);
2832 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2834 VM_CheckEmptyString (p);
2836 pic = Draw_CachePic (p);
2838 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2839 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2840 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2843 // CL_Video interface functions
2846 ========================
2849 float cin_open(string file, string name)
2850 ========================
2852 void VM_cin_open( void )
2857 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2859 file = PRVM_G_STRING( OFS_PARM0 );
2860 name = PRVM_G_STRING( OFS_PARM1 );
2862 VM_CheckEmptyString( file );
2863 VM_CheckEmptyString( name );
2865 if( CL_OpenVideo( file, name, MENUOWNER ) )
2866 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2868 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2872 ========================
2875 void cin_close(string name)
2876 ========================
2878 void VM_cin_close( void )
2882 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2884 name = PRVM_G_STRING( OFS_PARM0 );
2885 VM_CheckEmptyString( name );
2887 CL_CloseVideo( CL_GetVideo( name ) );
2891 ========================
2893 void cin_setstate(string name, float type)
2894 ========================
2896 void VM_cin_setstate( void )
2899 clvideostate_t state;
2902 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2904 name = PRVM_G_STRING( OFS_PARM0 );
2905 VM_CheckEmptyString( name );
2907 state = PRVM_G_FLOAT( OFS_PARM1 );
2909 video = CL_GetVideo( name );
2910 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2911 CL_SetVideoState( video, state );
2915 ========================
2918 float cin_getstate(string name)
2919 ========================
2921 void VM_cin_getstate( void )
2926 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2928 name = PRVM_G_STRING( OFS_PARM0 );
2929 VM_CheckEmptyString( name );
2931 video = CL_GetVideo( name );
2933 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2935 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2939 ========================
2942 void cin_restart(string name)
2943 ========================
2945 void VM_cin_restart( void )
2950 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2952 name = PRVM_G_STRING( OFS_PARM0 );
2953 VM_CheckEmptyString( name );
2955 video = CL_GetVideo( name );
2957 CL_RestartVideo( video );
2960 ////////////////////////////////////////
2961 // AltString functions
2962 ////////////////////////////////////////
2965 ========================
2968 float altstr_count(string)
2969 ========================
2971 void VM_altstr_count( void )
2976 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2978 altstr = PRVM_G_STRING( OFS_PARM0 );
2979 //VM_CheckEmptyString( altstr );
2981 for( count = 0, pos = altstr ; *pos ; pos++ )
2982 if( *pos == '\\' && !*++pos )
2984 else if( *pos == '\'' )
2987 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2991 ========================
2994 string altstr_prepare(string)
2995 ========================
2997 void VM_altstr_prepare( void )
3003 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3005 instr = PRVM_G_STRING( OFS_PARM0 );
3006 //VM_CheckEmptyString( instr );
3007 outstr = VM_GetTempString();
3009 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3018 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3022 ========================
3025 string altstr_get(string, float)
3026 ========================
3028 void VM_altstr_get( void )
3030 char *altstr, *pos, *outstr, *out;
3033 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3035 altstr = PRVM_G_STRING( OFS_PARM0 );
3036 //VM_CheckEmptyString( altstr );
3038 count = PRVM_G_FLOAT( OFS_PARM1 );
3039 count = count * 2 + 1;
3041 for( pos = altstr ; *pos && count ; pos++ )
3042 if( *pos == '\\' && !*++pos )
3044 else if( *pos == '\'' )
3048 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3052 outstr = VM_GetTempString();
3053 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3054 if( *pos == '\\' ) {
3059 } else if( *pos == '\'' )
3065 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3069 ========================
3072 string altstr_set(string altstr, float num, string set)
3073 ========================
3075 void VM_altstr_set( void )
3082 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3084 altstr = PRVM_G_STRING( OFS_PARM0 );
3085 //VM_CheckEmptyString( altstr );
3087 num = PRVM_G_FLOAT( OFS_PARM1 );
3089 str = PRVM_G_STRING( OFS_PARM2 );
3090 //VM_CheckEmptyString( str );
3092 outstr = out = VM_GetTempString();
3093 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3094 if( *in == '\\' && !*++in )
3096 else if( *in == '\'' )
3100 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3104 for( ; *str; *out++ = *str++ );
3105 // now jump over the old contents
3107 if( *in == '\'' || *in == '\\' && !*++in )
3111 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3116 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3119 void VM_Cmd_Init(void)
3121 // only init the stuff for the current prog
3122 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3127 void VM_Cmd_Reset(void)
3129 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3130 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3131 memheader_t *header;
3134 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3135 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3138 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3139 CL_PurgeOwner( MENUOWNER );
3141 VM_Files_CloseAll();
3144 //============================================================================
3147 char *vm_sv_extensions =
3150 prvm_builtin_t vm_sv_builtins[] = {
3151 0 // to be consistent with the old vm
3154 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3156 void VM_SV_Cmd_Init(void)
3160 void VM_SV_Cmd_Reset(void)
3164 //============================================================================
3167 char *vm_cl_extensions =
3170 prvm_builtin_t vm_cl_builtins[] = {
3171 0 // to be consistent with the old vm
3174 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3176 void VM_CL_Cmd_Init(void)
3180 void VM_CL_Cmd_Reset(void)
3184 //============================================================================
3187 char *vm_m_extensions =
3194 setmousetarget(float target)
3197 void VM_M_setmousetarget(void)
3199 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3201 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3204 in_client_mouse = false;
3207 in_client_mouse = true;
3210 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3218 float getmousetarget
3221 void VM_M_getmousetarget(void)
3223 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3226 PRVM_G_FLOAT(OFS_RETURN) = 2;
3228 PRVM_G_FLOAT(OFS_RETURN) = 1;
3237 setkeydest(float dest)
3240 void VM_M_setkeydest(void)
3242 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3244 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3248 key_dest = key_game;
3252 key_dest = key_menu;
3256 // key_dest = key_message
3259 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3270 void VM_M_getkeydest(void)
3272 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3274 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3278 PRVM_G_FLOAT(OFS_RETURN) = 0;
3281 PRVM_G_FLOAT(OFS_RETURN) = 2;
3285 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3288 PRVM_G_FLOAT(OFS_RETURN) = 3;
3296 callfunction(...,string function_name)
3300 mfunction_t *PRVM_ED_FindFunction (const char *name);
3301 void VM_M_callfunction(void)
3307 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3309 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3312 PRVM_ERROR("VM_M_callfunction: null string !\n");
3314 VM_CheckEmptyString(s);
3316 func = PRVM_ED_FindFunction(s);
3319 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3320 else if (func->first_statement < 0)
3322 // negative statements are built in functions
3323 int builtinnumber = -func->first_statement;
3324 prog->xfunction->builtinsprofile++;
3325 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3326 prog->builtins[builtinnumber]();
3328 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3333 PRVM_ExecuteProgram(func - prog->functions,"");
3342 float isfunction(string function_name)
3345 mfunction_t *PRVM_ED_FindFunction (const char *name);
3346 void VM_M_isfunction(void)
3351 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3353 s = PRVM_G_STRING(OFS_PARM0);
3356 PRVM_ERROR("VM_M_isfunction: null string !\n");
3358 VM_CheckEmptyString(s);
3360 func = PRVM_ED_FindFunction(s);
3363 PRVM_G_FLOAT(OFS_RETURN) = false;
3365 PRVM_G_FLOAT(OFS_RETURN) = true;
3372 writetofile(float fhandle, entity ent)
3375 void VM_M_writetofile(void)
3380 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3382 filenum = PRVM_G_FLOAT(OFS_PARM0);
3383 if (filenum < 0 || filenum >= MAX_VMFILES)
3385 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3388 if (VM_FILES[filenum] == NULL)
3390 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3394 ent = PRVM_G_EDICT(OFS_PARM1);
3397 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3401 PRVM_ED_Write (VM_FILES[filenum], ent);
3408 vector getresolution(float number)
3411 extern unsigned short video_resolutions[][2];
3412 void VM_M_getresolution(void)
3415 VM_SAFEPARMCOUNT(1, VM_getresolution);
3417 nr = PRVM_G_FLOAT(OFS_PARM0);
3420 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3421 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3422 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3429 string keynumtostring(float keynum)
3432 void VM_M_keynumtostring(void)
3436 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3438 keynum = PRVM_G_FLOAT(OFS_PARM0);
3440 tmp = VM_GetTempString();
3442 strcpy(tmp, Key_KeynumToString(keynum));
3444 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3451 float stringtokeynum(string key)
3454 void VM_M_stringtokeynum( void )
3457 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3459 str = PRVM_G_STRING( OFS_PARM0 );
3461 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3466 VM_M_findkeysforcommand
3468 string findkeysforcommand(string command)
3470 the returned string is an altstring
3473 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3475 void M_FindKeysForCommand(char *command, int *keys);
3476 void VM_M_findkeysforcommand(void)
3482 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3484 cmd = PRVM_G_STRING(OFS_PARM0);
3486 VM_CheckEmptyString(cmd);
3488 (ret = VM_GetTempString())[0] = 0;
3490 M_FindKeysForCommand(cmd, keys);
3492 for(i = 0; i < NUMKEYS; i++)
3493 ret = strcat(ret, va(" \'%i\'", keys[i]));
3495 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3500 VM_M_gethostcachestat
3502 float gethostcachestat(float type)
3507 0 hostcache_viewcount
3508 1 hostcache_totalcount
3516 void VM_M_gethostcachestat( void )
3519 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachestat );
3521 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3523 type = PRVM_G_FLOAT( OFS_PARM0 );
3527 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_viewcount;
3530 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_cachecount;
3532 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3535 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3538 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3541 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3544 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortbyfield;
3547 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortdescending;
3550 Con_Printf( "VM_M_gethostcachestat: bad type %i!\n", type );
3555 ========================
3556 VM_M_resethostcachemask
3558 resethostcachemask()
3559 ========================
3561 void VM_M_resethostcachemask( void )
3563 HostCache_ResetMask();
3568 ========================
3569 VM_M_sethostcachemaskstring
3571 sethostcachemaskstring(float field, string str)
3572 ========================
3574 void VM_M_sethostcachemaskstring( void )
3578 VM_SAFEPARMCOUNT( 2, VM_M_sethostcachemask );
3579 str = PRVM_G_STRING( OFS_PARM1 );
3581 PRVM_ERROR( "VM_M_sethostcachemask: null string passed!" );
3583 switch( (int) PRVM_G_FLOAT( OFS_PARM0 ) ) {
3585 strncpy( hostcache_currentmask.info.cname, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.cname) );
3588 strncpy( hostcache_currentmask.info.name, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.name) );
3591 strncpy( hostcache_currentmask.info.map, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.map) );
3594 strncpy( hostcache_currentmask.info.mod, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.mod) );
3597 strncpy( hostcache_currentmask.info.game, PRVM_G_STRING( OFS_PARM1 ), sizeof(hostcache_currentmask.info.game) );
3600 Con_Printf( "VM_M_sethostcachemask: Bad field number %i passed!\n", PRVM_G_INT( OFS_PARM0 ) );
3605 ========================
3606 VM_M_sethostcachemasknumber
3608 sethostcachemasknumber(float field, float num, float op)
3609 ========================
3611 void VM_M_sethostcachemasknumber( void )
3614 hostcache_maskop_t operand;
3615 VM_SAFEPARMCOUNT( 3, VM_M_sethostcachemasknumber );
3617 number = PRVM_G_FLOAT( OFS_PARM1 );
3618 operand = (int) PRVM_G_FLOAT( OFS_PARM2 );
3620 switch( (int) PRVM_G_FLOAT( OFS_PARM0 ) ) {
3621 case HCIF_MAXPLAYERS:
3622 hostcache_currentmask.info.maxplayers = number;
3623 hostcache_currentmask.maxplayerstest = operand;
3625 case HCIF_NUMPLAYERS:
3626 hostcache_currentmask.info.numplayers = number;
3627 hostcache_currentmask.numplayerstest = operand;
3630 hostcache_currentmask.info.ping = number;
3631 hostcache_currentmask.pingtest = operand;
3634 hostcache_currentmask.info.protocol = number;
3635 hostcache_currentmask.protocoltest = operand;
3638 Con_Printf( "VM_M_sethostcachemask: Bad field number %i passed!\n", PRVM_G_INT( OFS_PARM0 ) );
3644 ========================
3645 VM_M_resorthostcache
3648 ========================
3650 void VM_M_resorthostcache( void )
3652 HostCache_RebuildViewSet();
3657 VM_M_gethostcachestring
3659 string gethostcachestring(float field, float hostnr)
3662 void VM_M_gethostcachestring(void)
3667 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3669 PRVM_G_INT(OFS_RETURN) = 0;
3671 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3673 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3675 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3678 cache = hostcache_viewset[hostnr];
3679 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3681 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
3684 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
3687 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
3690 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
3693 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
3695 // TODO remove this again
3697 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
3700 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
3703 Con_Print("VM_M_gethostcachestring: bad field number passed!\n");
3709 VM_M_gethostcachenumber
3711 float gethostcachenumber(float field, float hostnr)
3714 void VM_M_gethostcachenumber(void)
3719 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3721 PRVM_G_INT(OFS_RETURN) = 0;
3723 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3725 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3727 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3730 cache = hostcache_viewset[hostnr];
3731 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3732 case HCIF_MAXPLAYERS:
3733 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3735 case HCIF_NUMPLAYERS:
3736 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3739 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3742 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3745 Con_Print("VM_M_gethostcachenumber: bad field number passed!\n");
3750 ========================
3751 VM_M_sethostcachesort
3753 sethostcachesort(float field, float descending)
3754 ========================
3756 void VM_M_sethostcachesort( void )
3758 VM_SAFEPARMCOUNT( 2, VM_M_sethostcachesort );
3760 hostcache_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3761 hostcache_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3765 ========================
3766 VM_M_refreshhostcache
3769 ========================
3771 void VM_M_refreshhostcache( void )
3773 HostCache_QueryList();
3776 prvm_builtin_t vm_m_builtins[] = {
3777 0, // to be consistent with the old vm
3778 // common builtings (mostly)
3855 VM_search_getfilename, // 77
3859 VM_itof, // isString
3863 VM_altstr_set, // 85
3877 VM_WriteEntity, // 408
3893 VM_drawresetcliparea,
3894 VM_getimagesize,// 460
3899 VM_cin_restart, // 465
3908 VM_M_setmousetarget,
3909 VM_M_getmousetarget,
3914 VM_M_keynumtostring,
3915 VM_M_findkeysforcommand,// 610
3916 VM_M_gethostcachestat,
3917 VM_M_gethostcachestring,
3918 VM_M_parseentitydata,
3919 VM_M_stringtokeynum,
3920 VM_M_resethostcachemask,
3921 VM_M_sethostcachemaskstring,
3922 VM_M_sethostcachemasknumber,
3923 VM_M_resorthostcache,
3924 VM_M_sethostcachesort,
3925 VM_M_refreshhostcache,
3926 VM_M_gethostcachenumber // 621
3929 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3931 void VM_M_Cmd_Init(void)
3936 void VM_M_Cmd_Reset(void)