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)
107 string altstr_ins(string altstr, float num, string set)
109 perhaps only : Menu : WriteMsg
110 ===============================
112 WriteByte(float data, float dest, float desto)
113 WriteChar(float data, float dest, float desto)
114 WriteShort(float data, float dest, float desto)
115 WriteLong(float data, float dest, float desto)
116 WriteAngle(float data, float dest, float desto)
117 WriteCoord(float data, float dest, float desto)
118 WriteString(string data, float dest, float desto)
119 WriteEntity(entity data, float dest, float desto)
121 Client & Menu : draw functions & video functions
122 ===================================================
124 float iscachedpic(string pic)
125 string precache_pic(string pic)
127 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
128 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
129 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
130 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
131 drawsetcliparea(float x, float y, float width, float height)
133 vector getimagesize(string pic)
135 float cin_open(string file, string name)
136 void cin_close(string name)
137 void cin_setstate(string name, float type)
138 float cin_getstate(string name)
139 void cin_restart(string name)
141 ==============================================================================
145 setkeydest(float dest)
147 setmousetarget(float target)
148 float getmousetarget()
150 callfunction(...,string function_name)
151 writetofile(float fhandle, entity ent)
152 float isfunction(string function_name)
153 vector getresolution(float number)
154 string keynumtostring(float keynum)
155 string findkeysforcommand(string command)
156 float getserverliststat(float type)
157 string getserverliststring(float fld, float hostnr)
159 parseentitydata(entity ent, string data)
161 float stringtokeynum(string key)
163 resetserverlistmasks()
164 setserverlistmaskstring(float mask, float fld, string str)
165 setserverlistmasknumber(float mask, float fld, float num, float op)
167 setserverlistsort(float field, float descending)
169 float getserverlistnumber(float fld, float hostnr)
170 float getserverlistindexforkey(string key)
171 addwantedserverlistkey(string key)
174 #include "quakedef.h"
175 #include "progdefs.h"
177 #include "clprogdefs.h"
178 #include "mprogdefs.h"
180 #include "cl_video.h"
182 //============================================================================
183 // nice helper macros
185 #ifndef VM_NOPARMCHECK
186 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
188 #define VM_SAFEPARMCOUNT(p,f)
191 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
193 #define e10 0,0,0,0,0,0,0,0,0,0
194 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
195 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
197 //============================================================================
200 // temp string handling
201 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
202 #define VM_STRINGTEMP_BUFFERS 16
203 #define VM_STRINGTEMP_LENGTH 4096
204 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
205 static int vm_string_tempindex = 0;
208 #define MAX_VMFILES 256
209 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
210 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
212 qfile_t *vm_files[MAX_PRVMFILES];
214 // qc fs search handling
215 #define MAX_VMSEARCHES 128
216 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
217 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
219 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
221 static char *VM_GetTempString(void)
224 s = vm_string_temp[vm_string_tempindex];
225 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
229 void VM_CheckEmptyString (const char *s)
232 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
235 //============================================================================
238 void VM_VarString(int first, char *out, int outlength)
244 outend = out + outlength - 1;
245 for (i = first;i < prog->argc && out < outend;i++)
247 s = PRVM_G_STRING((OFS_PARM0+i*3));
248 while (out < outend && *s)
258 returns true if the extension is supported by the server
260 checkextension(extensionname)
264 // kind of helper function
265 static qboolean checkextension(const char *name)
271 for (e = prog->extensionstring;*e;e++)
278 while (*e && *e != ' ')
280 if (e - start == len)
281 if (!strncasecmp(start, name, len))
289 void VM_checkextension (void)
291 VM_SAFEPARMCOUNT(1,VM_checkextension);
293 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
300 This is a TERMINAL error, which will kill off the entire prog.
309 char string[VM_STRINGTEMP_LENGTH];
311 VM_VarString(0, string, sizeof(string));
312 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
315 ed = PRVM_G_EDICT(prog->self->ofs);
319 PRVM_ERROR ("%s: Program error", PRVM_NAME);
326 Dumps out self, then an error message. The program is aborted and self is
327 removed, but the level can continue.
332 void VM_objerror (void)
335 char string[VM_STRINGTEMP_LENGTH];
337 VM_VarString(0, string, sizeof(string));
338 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
341 ed = PRVM_G_EDICT (prog->self->ofs);
347 // objerror has to display the object fields -> else call
348 PRVM_ERROR ("VM_objecterror: self not defined !\n");
353 VM_print (actually used only by client and menu)
362 char string[VM_STRINGTEMP_LENGTH];
364 VM_VarString(0, string, sizeof(string));
372 broadcast print to everyone on server
377 void VM_bprint (void)
379 char string[VM_STRINGTEMP_LENGTH];
383 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
387 VM_VarString(0, string, sizeof(string));
388 SV_BroadcastPrint(string);
393 VM_sprint (menu & client but only if server.active == true)
395 single print to a specific client
397 sprint(float clientnum,...[string])
400 void VM_sprint (void)
404 char string[VM_STRINGTEMP_LENGTH];
406 //find client for this entity
407 clientnum = PRVM_G_FLOAT(OFS_PARM0);
408 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
410 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
414 client = svs.clients + clientnum;
415 VM_VarString(1, string, sizeof(string));
416 MSG_WriteChar(&client->message,svc_print);
417 MSG_WriteString(&client->message, string);
424 single print to the screen
426 centerprint(clientent, value)
429 void VM_centerprint (void)
431 char string[VM_STRINGTEMP_LENGTH];
433 VM_VarString(0, string, sizeof(string));
434 SCR_CenterPrint(string);
441 vector normalize(vector)
444 void VM_normalize (void)
450 VM_SAFEPARMCOUNT(1,VM_normalize);
452 value1 = PRVM_G_VECTOR(OFS_PARM0);
454 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
458 newvalue[0] = newvalue[1] = newvalue[2] = 0;
462 newvalue[0] = value1[0] * new;
463 newvalue[1] = value1[1] * new;
464 newvalue[2] = value1[2] * new;
467 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
482 VM_SAFEPARMCOUNT(1,VM_vlen);
484 value1 = PRVM_G_VECTOR(OFS_PARM0);
486 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
489 PRVM_G_FLOAT(OFS_RETURN) = new;
496 float vectoyaw(vector)
499 void VM_vectoyaw (void)
504 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
506 value1 = PRVM_G_VECTOR(OFS_PARM0);
508 if (value1[1] == 0 && value1[0] == 0)
512 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
517 PRVM_G_FLOAT(OFS_RETURN) = yaw;
525 vector vectoangles(vector)
528 void VM_vectoangles (void)
534 VM_SAFEPARMCOUNT(1,VM_vectoangles);
536 value1 = PRVM_G_VECTOR(OFS_PARM0);
538 if (value1[1] == 0 && value1[0] == 0)
548 // LordHavoc: optimized a bit
551 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
555 else if (value1[1] > 0)
560 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
561 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
566 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
567 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
568 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
575 Returns a number from 0<= num < 1
580 void VM_random (void)
582 VM_SAFEPARMCOUNT(0,VM_random);
584 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
591 Each entity can have eight independant sound sources, like voice,
594 Channel 0 is an auto-allocate channel, the others override anything
595 already running on that entity/channel pair.
597 An attenuation of 0 will play full volume everywhere in the level.
598 Larger attenuations will drop off.
611 entity = G_EDICT(OFS_PARM0);
612 channel = G_FLOAT(OFS_PARM1);
613 sample = G_STRING(OFS_PARM2);
614 volume = G_FLOAT(OFS_PARM3) * 255;
615 attenuation = G_FLOAT(OFS_PARM4);
617 if (volume < 0 || volume > 255)
618 Host_Error ("SV_StartSound: volume = %i", volume);
620 if (attenuation < 0 || attenuation > 4)
621 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
623 if (channel < 0 || channel > 7)
624 Host_Error ("SV_StartSound: channel = %i", channel);
626 SV_StartSound (entity, channel, sample, volume, attenuation);
634 localsound(string sample)
637 void VM_localsound(void)
641 VM_SAFEPARMCOUNT(1,VM_localsound);
643 s = PRVM_G_STRING(OFS_PARM0);
645 if(!S_LocalSound (s))
647 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
648 PRVM_G_FLOAT(OFS_RETURN) = -4;
652 PRVM_G_FLOAT(OFS_RETURN) = 1;
664 PRVM_ERROR ("%s: break statement", PRVM_NAME);
667 //============================================================================
673 Sends text over to the client's execution buffer
675 [localcmd (string) or]
679 void VM_localcmd (void)
681 VM_SAFEPARMCOUNT(1,VM_localcmd);
683 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
695 VM_SAFEPARMCOUNT(1,VM_cvar);
697 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
704 const string str_cvar (string)
707 void VM_str_cvar(void)
711 const char *cvar_string;
712 VM_SAFEPARMCOUNT(1,VM_str_cvar);
714 name = PRVM_G_STRING(OFS_PARM0);
717 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
719 VM_CheckEmptyString(name);
721 out = VM_GetTempString();
723 cvar_string = Cvar_VariableString(name);
725 strcpy(out, cvar_string);
727 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(out);
734 void cvar_set (string,string)
737 void VM_cvar_set (void)
739 VM_SAFEPARMCOUNT(2,VM_cvar_set);
741 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
751 void VM_dprint (void)
753 char string[VM_STRINGTEMP_LENGTH];
754 if (developer.integer)
756 VM_VarString(0, string, sizeof(string));
757 Con_Printf("%s: %s", PRVM_NAME, string);
774 VM_SAFEPARMCOUNT(1, VM_ftos);
776 v = PRVM_G_FLOAT(OFS_PARM0);
778 s = VM_GetTempString();
779 if ((float)((int)v) == v)
780 sprintf(s, "%i", (int)v);
783 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
798 VM_SAFEPARMCOUNT(1,VM_fabs);
800 v = PRVM_G_FLOAT(OFS_PARM0);
801 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
816 VM_SAFEPARMCOUNT(1,VM_vtos);
818 s = VM_GetTempString();
819 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]);
820 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
835 VM_SAFEPARMCOUNT(1, VM_etos);
837 s = VM_GetTempString();
838 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
839 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
846 float stof(...[string])
851 char string[VM_STRINGTEMP_LENGTH];
852 VM_VarString(0, string, sizeof(string));
853 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
857 ========================
861 ========================
865 VM_SAFEPARMCOUNT(1, VM_itof);
866 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
870 ========================
874 ========================
879 VM_SAFEPARMCOUNT(1, VM_ftoi);
881 ent = PRVM_G_FLOAT(OFS_PARM0);
882 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
883 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
885 PRVM_G_INT(OFS_RETURN) = ent;
899 prog->xfunction->builtinsprofile += 20;
900 ed = PRVM_ED_Alloc();
912 void VM_remove (void)
915 prog->xfunction->builtinsprofile += 20;
917 VM_SAFEPARMCOUNT(1, VM_remove);
919 ed = PRVM_G_EDICT(OFS_PARM0);
920 // if (ed == prog->edicts)
921 // PRVM_ERROR ("remove: tried to remove world\n");
922 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
923 // Host_Error("remove: tried to remove a client\n");
931 entity find(entity start, .string field, string match)
942 VM_SAFEPARMCOUNT(3,VM_find);
944 e = PRVM_G_EDICTNUM(OFS_PARM0);
945 f = PRVM_G_INT(OFS_PARM1);
946 s = PRVM_G_STRING(OFS_PARM2);
950 // return reserved edict 0 (could be used for whatever the prog wants)
951 VM_RETURN_EDICT(prog->edicts);
955 for (e++ ; e < prog->num_edicts ; e++)
957 prog->xfunction->builtinsprofile++;
958 ed = PRVM_EDICT_NUM(e);
961 t = PRVM_E_STRING(ed,f);
971 VM_RETURN_EDICT(prog->edicts);
978 entity findfloat(entity start, .float field, float match)
979 entity findentity(entity start, .entity field, entity match)
982 // LordHavoc: added this for searching float, int, and entity reference fields
983 void VM_findfloat (void)
990 VM_SAFEPARMCOUNT(3,VM_findfloat);
992 e = PRVM_G_EDICTNUM(OFS_PARM0);
993 f = PRVM_G_INT(OFS_PARM1);
994 s = PRVM_G_FLOAT(OFS_PARM2);
996 for (e++ ; e < prog->num_edicts ; e++)
998 prog->xfunction->builtinsprofile++;
999 ed = PRVM_EDICT_NUM(e);
1002 if (PRVM_E_FLOAT(ed,f) == s)
1004 VM_RETURN_EDICT(ed);
1009 VM_RETURN_EDICT(prog->edicts);
1016 entity findchain(.string field, string match)
1019 int PRVM_ED_FindFieldOffset(const char *field);
1020 // chained search for strings in entity fields
1021 // entity(.string field, string match) findchain = #402;
1022 void VM_findchain (void)
1028 prvm_edict_t *ent, *chain;
1030 VM_SAFEPARMCOUNT(2,VM_findchain);
1032 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1033 if(!prog->flag & PRVM_FE_CHAIN)
1034 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1036 chain_of = PRVM_ED_FindFieldOffset ("chain");
1038 chain = prog->edicts;
1040 f = PRVM_G_INT(OFS_PARM0);
1041 s = PRVM_G_STRING(OFS_PARM1);
1044 VM_RETURN_EDICT(prog->edicts);
1048 ent = PRVM_NEXT_EDICT(prog->edicts);
1049 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1051 prog->xfunction->builtinsprofile++;
1054 t = PRVM_E_STRING(ent,f);
1060 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1064 VM_RETURN_EDICT(chain);
1071 entity findchainfloat(.string field, float match)
1072 entity findchainentity(.string field, entity match)
1075 // LordHavoc: chained search for float, int, and entity reference fields
1076 // entity(.string field, float match) findchainfloat = #403;
1077 void VM_findchainfloat (void)
1083 prvm_edict_t *ent, *chain;
1085 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1087 if(!prog->flag & PRVM_FE_CHAIN)
1088 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1090 chain_of = PRVM_ED_FindFieldOffset ("chain");
1092 chain = (prvm_edict_t *)prog->edicts;
1094 f = PRVM_G_INT(OFS_PARM0);
1095 s = PRVM_G_FLOAT(OFS_PARM1);
1097 ent = PRVM_NEXT_EDICT(prog->edicts);
1098 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1100 prog->xfunction->builtinsprofile++;
1103 if (PRVM_E_FLOAT(ent,f) != s)
1106 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1110 VM_RETURN_EDICT(chain);
1117 string precache_file(string)
1120 void VM_precache_file (void)
1121 { // precache_file is only used to copy files with qcc, it does nothing
1122 VM_SAFEPARMCOUNT(1,VM_precache_file);
1124 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1131 used instead of the other VM_precache_* functions in the builtin list
1135 void VM_precache_error (void)
1137 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1144 string precache_sound (string sample)
1147 void VM_precache_sound (void)
1151 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1153 s = PRVM_G_STRING(OFS_PARM0);
1154 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1155 VM_CheckEmptyString (s);
1157 if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
1158 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1168 void VM_coredump (void)
1170 VM_SAFEPARMCOUNT(0,VM_coredump);
1172 Cbuf_AddText("prvm_edicts ");
1173 Cbuf_AddText(PRVM_NAME);
1184 void PRVM_StackTrace(void);
1185 void VM_stackdump (void)
1187 VM_SAFEPARMCOUNT(0, VM_stackdump);
1202 VM_SAFEPARMCOUNT(0, VM_crash);
1204 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1214 void VM_traceon (void)
1216 VM_SAFEPARMCOUNT(0,VM_traceon);
1228 void VM_traceoff (void)
1230 VM_SAFEPARMCOUNT(0,VM_traceoff);
1232 prog->trace = false;
1242 void VM_eprint (void)
1244 VM_SAFEPARMCOUNT(1,VM_eprint);
1246 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1260 VM_SAFEPARMCOUNT(1,VM_rint);
1262 f = PRVM_G_FLOAT(OFS_PARM0);
1264 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1266 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1276 void VM_floor (void)
1278 VM_SAFEPARMCOUNT(1,VM_floor);
1280 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1292 VM_SAFEPARMCOUNT(1,VM_ceil);
1294 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1302 entity nextent(entity)
1305 void VM_nextent (void)
1310 i = PRVM_G_EDICTNUM(OFS_PARM0);
1313 prog->xfunction->builtinsprofile++;
1315 if (i == prog->num_edicts)
1317 VM_RETURN_EDICT(prog->edicts);
1320 ent = PRVM_EDICT_NUM(i);
1321 if (!ent->p.e->free)
1323 VM_RETURN_EDICT(ent);
1330 ===============================================================================
1333 used only for client and menu
1334 severs uses VM_SV_...
1336 Write*(* data, float type, float to)
1338 ===============================================================================
1341 #define MSG_BROADCAST 0 // unreliable to all
1342 #define MSG_ONE 1 // reliable to one (msg_entity)
1343 #define MSG_ALL 2 // reliable to all
1344 #define MSG_INIT 3 // write to the init string
1346 sizebuf_t *VM_WriteDest (void)
1352 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1354 dest = G_FLOAT(OFS_PARM1);
1358 return &sv.datagram;
1361 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1362 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1363 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1365 return &svs.clients[destclient].message;
1368 return &sv.reliable_datagram;
1374 PRVM_ERROR ("WriteDest: bad destination");
1381 void VM_WriteByte (void)
1383 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1386 void VM_WriteChar (void)
1388 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1391 void VM_WriteShort (void)
1393 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1396 void VM_WriteLong (void)
1398 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1401 void VM_WriteAngle (void)
1403 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1406 void VM_WriteCoord (void)
1408 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1411 void VM_WriteString (void)
1413 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1416 void VM_WriteEntity (void)
1418 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1421 //=============================================================================
1428 changelevel(string map)
1431 void VM_changelevel (void)
1435 VM_SAFEPARMCOUNT(1, VM_changelevel);
1439 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1443 // make sure we don't issue two changelevels
1444 if (svs.changelevel_issued)
1446 svs.changelevel_issued = true;
1448 s = PRVM_G_STRING(OFS_PARM0);
1449 Cbuf_AddText (va("changelevel %s\n",s));
1461 VM_SAFEPARMCOUNT(1,VM_sin);
1462 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1473 VM_SAFEPARMCOUNT(1,VM_cos);
1474 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1486 VM_SAFEPARMCOUNT(1,VM_sqrt);
1487 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1494 Returns a vector of length < 1 and > 0
1499 void VM_randomvec (void)
1504 VM_SAFEPARMCOUNT(0, VM_randomvec);
1509 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1510 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1511 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1513 while (DotProduct(temp, temp) >= 1);
1514 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1517 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1518 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1519 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1520 // length returned always > 0
1521 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1522 VectorScale(temp,length, temp);*/
1523 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1526 //=============================================================================
1532 float registercvar (string name, string value, float flags)
1535 void VM_registercvar (void)
1537 const char *name, *value;
1540 VM_SAFEPARMCOUNT(3,VM_registercvar);
1542 name = PRVM_G_STRING(OFS_PARM0);
1543 value = PRVM_G_STRING(OFS_PARM1);
1544 flags = PRVM_G_FLOAT(OFS_PARM2);
1545 PRVM_G_FLOAT(OFS_RETURN) = 0;
1547 if(flags > CVAR_MAXFLAGSVAL)
1550 // first check to see if it has already been defined
1551 if (Cvar_FindVar (name))
1554 // check for overlap with a command
1555 if (Cmd_Exists (name))
1557 Con_Printf("VM_registercvar: %s is a command\n", name);
1561 Cvar_Get(name, value, flags);
1563 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1570 returns the minimum of two supplied floats
1572 float min(float a, float b, ...[float])
1577 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1578 if (prog->argc == 2)
1579 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1580 else if (prog->argc >= 3)
1583 float f = PRVM_G_FLOAT(OFS_PARM0);
1584 for (i = 1;i < prog->argc;i++)
1585 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1586 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1587 PRVM_G_FLOAT(OFS_RETURN) = f;
1590 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1597 returns the maximum of two supplied floats
1599 float max(float a, float b, ...[float])
1604 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1605 if (prog->argc == 2)
1606 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1607 else if (prog->argc >= 3)
1610 float f = PRVM_G_FLOAT(OFS_PARM0);
1611 for (i = 1;i < prog->argc;i++)
1612 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1613 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1614 PRVM_G_FLOAT(OFS_RETURN) = f;
1617 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1624 returns number bounded by supplied range
1626 float bound(float min, float value, float max)
1629 void VM_bound (void)
1631 VM_SAFEPARMCOUNT(3,VM_bound);
1632 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1639 returns a raised to power b
1641 float pow(float a, float b)
1646 VM_SAFEPARMCOUNT(2,VM_pow);
1647 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1654 copies data from one entity to another
1656 copyentity(entity src, entity dst)
1659 void VM_copyentity (void)
1661 prvm_edict_t *in, *out;
1662 VM_SAFEPARMCOUNT(2,VM_copyentity);
1663 in = PRVM_G_EDICT(OFS_PARM0);
1664 out = PRVM_G_EDICT(OFS_PARM1);
1665 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1672 sets the color of a client and broadcasts the update to all connected clients
1674 setcolor(clientent, value)
1677 /*void PF_setcolor (void)
1683 entnum = G_EDICTNUM(OFS_PARM0);
1684 i = G_FLOAT(OFS_PARM1);
1686 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1688 Con_Print("tried to setcolor a non-client\n");
1692 client = svs.clients + entnum-1;
1693 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1696 client->old_colors = i;
1697 client->edict->v->team = (i & 15) + 1;
1699 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1700 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1701 MSG_WriteByte (&sv.reliable_datagram, i);
1704 void VM_Files_Init(void)
1706 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1709 void VM_Files_CloseAll(void)
1712 for (i = 0;i < MAX_VMFILES;i++)
1715 FS_Close(VM_FILES[i]);
1716 //VM_FILES[i] = NULL;
1718 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1725 float fopen(string filename, float mode)
1728 // float(string filename, float mode) fopen = #110;
1729 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1730 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1734 const char *modestring, *filename;
1736 VM_SAFEPARMCOUNT(2,VM_fopen);
1738 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1739 if (VM_FILES[filenum] == NULL)
1741 if (filenum >= MAX_VMFILES)
1743 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1744 PRVM_G_FLOAT(OFS_RETURN) = -2;
1747 mode = PRVM_G_FLOAT(OFS_PARM1);
1750 case 0: // FILE_READ
1753 case 1: // FILE_APPEND
1756 case 2: // FILE_WRITE
1760 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1761 PRVM_G_FLOAT(OFS_RETURN) = -3;
1764 filename = PRVM_G_STRING(OFS_PARM0);
1765 // .. is parent directory on many platforms
1766 // / is parent directory on Amiga
1767 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1768 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1769 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1771 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1772 PRVM_G_FLOAT(OFS_RETURN) = -4;
1775 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
1776 if (VM_FILES[filenum] == NULL && mode == 0)
1777 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false, false);
1779 if (VM_FILES[filenum] == NULL)
1780 PRVM_G_FLOAT(OFS_RETURN) = -1;
1782 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1789 fclose(float fhandle)
1792 //void(float fhandle) fclose = #111; // closes a file
1793 void VM_fclose(void)
1797 VM_SAFEPARMCOUNT(1,VM_fclose);
1799 filenum = PRVM_G_FLOAT(OFS_PARM0);
1800 if (filenum < 0 || filenum >= MAX_VMFILES)
1802 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1805 if (VM_FILES[filenum] == NULL)
1807 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1810 FS_Close(VM_FILES[filenum]);
1811 VM_FILES[filenum] = NULL;
1818 string fgets(float fhandle)
1821 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1825 static char string[VM_STRINGTEMP_LENGTH];
1828 VM_SAFEPARMCOUNT(1,VM_fgets);
1830 filenum = PRVM_G_FLOAT(OFS_PARM0);
1831 if (filenum < 0 || filenum >= MAX_VMFILES)
1833 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1836 if (VM_FILES[filenum] == NULL)
1838 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1844 c = FS_Getc(VM_FILES[filenum]);
1845 if (c == '\r' || c == '\n' || c < 0)
1847 if (end < VM_STRINGTEMP_LENGTH - 1)
1851 // remove \n following \r
1854 c = FS_Getc(VM_FILES[filenum]);
1856 FS_UnGetc(VM_FILES[filenum], (unsigned char)c);
1858 if (developer.integer >= 3)
1859 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1861 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
1863 PRVM_G_INT(OFS_RETURN) = 0;
1870 fputs(float fhandle, string s)
1873 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1877 char string[VM_STRINGTEMP_LENGTH];
1880 VM_SAFEPARMCOUNT(2,VM_fputs);
1882 filenum = PRVM_G_FLOAT(OFS_PARM0);
1883 if (filenum < 0 || filenum >= MAX_VMFILES)
1885 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1888 if (VM_FILES[filenum] == NULL)
1890 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1893 VM_VarString(1, string, sizeof(string));
1894 if ((stringlength = strlen(string)))
1895 FS_Write(VM_FILES[filenum], string, stringlength);
1896 if (developer.integer)
1897 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1904 float strlen(string s)
1907 //float(string s) strlen = #114; // returns how many characters are in a string
1908 void VM_strlen(void)
1912 VM_SAFEPARMCOUNT(1,VM_strlen);
1914 s = PRVM_G_STRING(OFS_PARM0);
1916 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1918 PRVM_G_FLOAT(OFS_RETURN) = 0;
1925 string strcat(string,string,...[string])
1928 //string(string s1, string s2) strcat = #115;
1929 // concatenates two strings (for example "abc", "def" would return "abcdef")
1930 // and returns as a tempstring
1931 void VM_strcat(void)
1936 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1938 s = VM_GetTempString();
1939 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1940 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1947 string substring(string s, float start, float length)
1950 // string(string s, float start, float length) substring = #116;
1951 // returns a section of a string as a tempstring
1952 void VM_substring(void)
1954 int i, start, length;
1958 VM_SAFEPARMCOUNT(3,VM_substring);
1960 string = VM_GetTempString();
1961 s = PRVM_G_STRING(OFS_PARM0);
1962 start = PRVM_G_FLOAT(OFS_PARM1);
1963 length = PRVM_G_FLOAT(OFS_PARM2);
1966 for (i = 0;i < start && *s;i++, s++);
1967 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1970 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
1977 vector stov(string s)
1980 //vector(string s) stov = #117; // returns vector value from a string
1983 char string[VM_STRINGTEMP_LENGTH];
1985 VM_SAFEPARMCOUNT(1,VM_stov);
1987 VM_VarString(0, string, sizeof(string));
1988 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1995 string strzone(string s)
1998 //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)
1999 void VM_strzone(void)
2004 VM_SAFEPARMCOUNT(1,VM_strzone);
2006 in = PRVM_G_STRING(OFS_PARM0);
2007 out = PRVM_AllocString(strlen(in) + 1);
2009 PRVM_G_INT(OFS_RETURN) = PRVM_SetQCString(out);
2019 //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!!!)
2020 void VM_strunzone(void)
2022 VM_SAFEPARMCOUNT(1,VM_strunzone);
2023 PRVM_FreeString((char *)PRVM_G_STRING(OFS_PARM0));
2028 VM_command (used by client and menu)
2030 clientcommand(float client, string s) (for client and menu)
2033 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2034 //this function originally written by KrimZon, made shorter by LordHavoc
2035 void VM_clcommand (void)
2037 client_t *temp_client;
2040 VM_SAFEPARMCOUNT(2,VM_clcommand);
2042 i = PRVM_G_FLOAT(OFS_PARM0);
2043 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2045 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2049 temp_client = host_client;
2050 host_client = svs.clients + i;
2051 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2052 host_client = temp_client;
2060 float tokenize(string s)
2063 //float(string s) tokenize = #441;
2064 // takes apart a string into individal words (access them with argv), returns how many
2065 // this function originally written by KrimZon, made shorter by LordHavoc
2066 static char **tokens = NULL;
2067 static int max_tokens, num_tokens = 0;
2068 void VM_tokenize (void)
2070 const char *p, *str;
2072 VM_SAFEPARMCOUNT(1,VM_tokenize);
2074 str = PRVM_G_STRING(OFS_PARM0);
2079 for (i=0;i<num_tokens;i++)
2085 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2086 max_tokens = strlen(str);
2088 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2090 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2091 strcpy(tokens[num_tokens], com_token);
2094 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2101 string argv(float n)
2104 //string(float n) argv = #442;
2105 // returns a word from the tokenized string (returns nothing for an invalid index)
2106 // this function originally written by KrimZon, made shorter by LordHavoc
2111 VM_SAFEPARMCOUNT(1,VM_argv);
2113 token_num = PRVM_G_FLOAT(OFS_PARM0);
2114 if (token_num >= 0 && token_num < num_tokens)
2115 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]);
2117 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
2121 //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)
2122 void PF_setattachment (void)
2124 edict_t *e = G_EDICT(OFS_PARM0);
2125 edict_t *tagentity = G_EDICT(OFS_PARM1);
2126 char *tagname = G_STRING(OFS_PARM2);
2131 if (tagentity == NULL)
2132 tagentity = sv.edicts;
2134 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2136 v->edict = EDICT_TO_PROG(tagentity);
2138 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2141 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2143 modelindex = (int)tagentity->v->modelindex;
2144 if (modelindex >= 0 && modelindex < MAX_MODELS)
2146 model = sv.models[modelindex];
2147 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2148 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2149 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2151 // FIXME: use a model function to get tag info (need to handle skeletal)
2152 if (v->_float == 0 && model->num_tags)
2153 for (i = 0;i < model->num_tags;i++)
2154 if (!strcmp(tagname, model->data_tags[i].name))
2157 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);
2160 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));
2171 void VM_isserver(void)
2173 VM_SAFEPARMCOUNT(0,VM_serverstate);
2175 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2185 void VM_clientcount(void)
2187 VM_SAFEPARMCOUNT(0,VM_clientcount);
2189 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2199 void VM_clientstate(void)
2201 VM_SAFEPARMCOUNT(0,VM_clientstate);
2203 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2210 float getostype(void)
2212 */ // not used at the moment -> not included in the common list
2213 void VM_getostype(void)
2215 VM_SAFEPARMCOUNT(0,VM_getostype);
2220 OS_MAC - not supported
2224 PRVM_G_FLOAT(OFS_RETURN) = 0;
2226 PRVM_G_FLOAT(OFS_RETURN) = 2;
2228 PRVM_G_FLOAT(OFS_RETURN) = 1;
2236 vector getmousepos()
2239 void VM_getmousepos(void)
2242 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2244 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x * vid_conwidth.integer / vid.width;
2245 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y * vid_conheight.integer / vid.height;
2246 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2256 void VM_gettime(void)
2258 VM_SAFEPARMCOUNT(0,VM_gettime);
2260 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2267 loadfromdata(string data)
2270 void VM_loadfromdata(void)
2272 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2274 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2278 ========================
2279 VM_M_parseentitydata
2281 parseentitydata(entity ent, string data)
2282 ========================
2284 void VM_M_parseentitydata(void)
2289 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2291 // get edict and test it
2292 ent = PRVM_G_EDICT(OFS_PARM0);
2294 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2296 data = PRVM_G_STRING(OFS_PARM1);
2298 // parse the opening brace
2299 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2300 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2302 PRVM_ED_ParseEdict (data, ent);
2309 loadfromfile(string file)
2312 void VM_loadfromfile(void)
2314 const char *filename;
2317 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2319 filename = PRVM_G_STRING(OFS_PARM0);
2320 // .. is parent directory on many platforms
2321 // / is parent directory on Amiga
2322 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2323 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2324 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2326 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2327 PRVM_G_FLOAT(OFS_RETURN) = -4;
2331 // not conform with VM_fopen
2332 data = FS_LoadFile(filename, tempmempool, false);
2334 PRVM_G_FLOAT(OFS_RETURN) = -1;
2336 PRVM_ED_LoadFromFile(data);
2347 float mod(float val, float m)
2350 void VM_modulo(void)
2353 VM_SAFEPARMCOUNT(2,VM_module);
2355 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2356 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2358 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2361 void VM_Search_Init(void)
2363 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2366 void VM_Search_Reset(void)
2369 // reset the fssearch list
2370 for(i = 0; i < MAX_VMSEARCHES; i++)
2371 if(VM_SEARCHLIST[i])
2372 FS_FreeSearch(VM_SEARCHLIST[i]);
2373 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2380 float search_begin(string pattern, float caseinsensitive, float quiet)
2383 void VM_search_begin(void)
2386 const char *pattern;
2387 int caseinsens, quiet;
2389 VM_SAFEPARMCOUNT(3, VM_search_begin);
2391 pattern = PRVM_G_STRING(OFS_PARM0);
2393 VM_CheckEmptyString(pattern);
2395 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2396 quiet = PRVM_G_FLOAT(OFS_PARM2);
2398 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2399 if(!VM_SEARCHLIST[handle])
2402 if(handle >= MAX_VMSEARCHES)
2404 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2405 PRVM_G_FLOAT(OFS_RETURN) = -2;
2409 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2410 PRVM_G_FLOAT(OFS_RETURN) = -1;
2412 PRVM_G_FLOAT(OFS_RETURN) = handle;
2419 void search_end(float handle)
2422 void VM_search_end(void)
2425 VM_SAFEPARMCOUNT(1, VM_search_end);
2427 handle = PRVM_G_FLOAT(OFS_PARM0);
2429 if(handle < 0 || handle >= MAX_VMSEARCHES)
2431 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2434 if(VM_SEARCHLIST[handle] == NULL)
2436 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2440 FS_FreeSearch(VM_SEARCHLIST[handle]);
2441 VM_SEARCHLIST[handle] = NULL;
2448 float search_getsize(float handle)
2451 void VM_search_getsize(void)
2454 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2456 handle = PRVM_G_FLOAT(OFS_PARM0);
2458 if(handle < 0 || handle >= MAX_VMSEARCHES)
2460 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2463 if(VM_SEARCHLIST[handle] == NULL)
2465 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2469 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2474 VM_search_getfilename
2476 string search_getfilename(float handle, float num)
2479 void VM_search_getfilename(void)
2481 int handle, filenum;
2483 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2485 handle = PRVM_G_FLOAT(OFS_PARM0);
2486 filenum = PRVM_G_FLOAT(OFS_PARM1);
2488 if(handle < 0 || handle >= MAX_VMSEARCHES)
2490 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2493 if(VM_SEARCHLIST[handle] == NULL)
2495 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2498 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2500 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2504 tmp = VM_GetTempString();
2505 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2507 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
2514 string chr(float ascii)
2520 VM_SAFEPARMCOUNT(1, VM_chr);
2522 tmp = VM_GetTempString();
2523 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2526 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
2529 //=============================================================================
2530 // Draw builtins (client & menu)
2536 float iscachedpic(string pic)
2539 void VM_iscachedpic(void)
2541 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2543 // drawq hasnt such a function, thus always return true
2544 PRVM_G_FLOAT(OFS_RETURN) = false;
2551 string precache_pic(string pic)
2554 void VM_precache_pic(void)
2558 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2560 s = PRVM_G_STRING(OFS_PARM0);
2561 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2564 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2566 VM_CheckEmptyString (s);
2568 // AK Draw_CachePic is supposed to always return a valid pointer
2569 if( Draw_CachePic(s, false)->tex == r_texture_notexture )
2570 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
2580 void VM_freepic(void)
2584 VM_SAFEPARMCOUNT(1,VM_freepic);
2586 s = PRVM_G_STRING(OFS_PARM0);
2589 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2591 VM_CheckEmptyString (s);
2600 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2603 void VM_drawcharacter(void)
2605 float *pos,*scale,*rgb;
2608 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2610 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2613 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2614 PRVM_G_FLOAT(OFS_RETURN) = -1;
2618 pos = PRVM_G_VECTOR(OFS_PARM0);
2619 scale = PRVM_G_VECTOR(OFS_PARM2);
2620 rgb = PRVM_G_VECTOR(OFS_PARM3);
2621 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2623 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2625 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2626 PRVM_G_FLOAT(OFS_RETURN) = -2;
2630 if(pos[2] || scale[2])
2631 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")));
2633 if(!scale[0] || !scale[1])
2635 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2636 PRVM_G_FLOAT(OFS_RETURN) = -3;
2640 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2641 PRVM_G_FLOAT(OFS_RETURN) = 1;
2648 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2651 void VM_drawstring(void)
2653 float *pos,*scale,*rgb;
2656 VM_SAFEPARMCOUNT(6,VM_drawstring);
2658 string = PRVM_G_STRING(OFS_PARM1);
2661 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2662 PRVM_G_FLOAT(OFS_RETURN) = -1;
2666 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
2668 pos = PRVM_G_VECTOR(OFS_PARM0);
2669 scale = PRVM_G_VECTOR(OFS_PARM2);
2670 rgb = PRVM_G_VECTOR(OFS_PARM3);
2671 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2673 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2675 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2676 PRVM_G_FLOAT(OFS_RETURN) = -2;
2680 if(!scale[0] || !scale[1])
2682 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2683 PRVM_G_FLOAT(OFS_RETURN) = -3;
2687 if(pos[2] || scale[2])
2688 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")));
2690 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2691 PRVM_G_FLOAT(OFS_RETURN) = 1;
2697 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2700 void VM_drawpic(void)
2703 float *size, *pos, *rgb;
2706 VM_SAFEPARMCOUNT(6,VM_drawpic);
2708 pic = PRVM_G_STRING(OFS_PARM1);
2712 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2713 PRVM_G_FLOAT(OFS_RETURN) = -1;
2717 VM_CheckEmptyString (pic);
2719 // is pic cached ? no function yet for that
2722 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2723 PRVM_G_FLOAT(OFS_RETURN) = -4;
2727 pos = PRVM_G_VECTOR(OFS_PARM0);
2728 size = PRVM_G_VECTOR(OFS_PARM2);
2729 rgb = PRVM_G_VECTOR(OFS_PARM3);
2730 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2732 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2734 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2735 PRVM_G_FLOAT(OFS_RETURN) = -2;
2739 if(pos[2] || size[2])
2740 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")));
2742 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2743 PRVM_G_FLOAT(OFS_RETURN) = 1;
2750 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2753 void VM_drawfill(void)
2755 float *size, *pos, *rgb;
2758 VM_SAFEPARMCOUNT(5,VM_drawfill);
2761 pos = PRVM_G_VECTOR(OFS_PARM0);
2762 size = PRVM_G_VECTOR(OFS_PARM1);
2763 rgb = PRVM_G_VECTOR(OFS_PARM2);
2764 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2766 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2768 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2769 PRVM_G_FLOAT(OFS_RETURN) = -2;
2773 if(pos[2] || size[2])
2774 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")));
2776 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2777 PRVM_G_FLOAT(OFS_RETURN) = 1;
2784 drawsetcliparea(float x, float y, float width, float height)
2787 void VM_drawsetcliparea(void)
2790 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2792 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid_conwidth.integer);
2793 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid_conheight.integer);
2794 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid_conwidth.integer - x));
2795 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid_conheight.integer - y));
2797 DrawQ_SetClipArea(x, y, w, h);
2802 VM_drawresetcliparea
2807 void VM_drawresetcliparea(void)
2809 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2811 DrawQ_ResetClipArea();
2818 vector getimagesize(string pic)
2821 void VM_getimagesize(void)
2826 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2828 p = PRVM_G_STRING(OFS_PARM0);
2831 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2833 VM_CheckEmptyString (p);
2835 pic = Draw_CachePic (p, false);
2837 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2838 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2839 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2842 // CL_Video interface functions
2845 ========================
2848 float cin_open(string file, string name)
2849 ========================
2851 void VM_cin_open( void )
2856 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2858 file = PRVM_G_STRING( OFS_PARM0 );
2859 name = PRVM_G_STRING( OFS_PARM1 );
2861 VM_CheckEmptyString( file );
2862 VM_CheckEmptyString( name );
2864 if( CL_OpenVideo( file, name, MENUOWNER ) )
2865 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2867 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2871 ========================
2874 void cin_close(string name)
2875 ========================
2877 void VM_cin_close( void )
2881 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2883 name = PRVM_G_STRING( OFS_PARM0 );
2884 VM_CheckEmptyString( name );
2886 CL_CloseVideo( CL_GetVideo( name ) );
2890 ========================
2892 void cin_setstate(string name, float type)
2893 ========================
2895 void VM_cin_setstate( void )
2898 clvideostate_t state;
2901 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2903 name = PRVM_G_STRING( OFS_PARM0 );
2904 VM_CheckEmptyString( name );
2906 state = PRVM_G_FLOAT( OFS_PARM1 );
2908 video = CL_GetVideo( name );
2909 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2910 CL_SetVideoState( video, state );
2914 ========================
2917 float cin_getstate(string name)
2918 ========================
2920 void VM_cin_getstate( void )
2925 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2927 name = PRVM_G_STRING( OFS_PARM0 );
2928 VM_CheckEmptyString( name );
2930 video = CL_GetVideo( name );
2932 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2934 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2938 ========================
2941 void cin_restart(string name)
2942 ========================
2944 void VM_cin_restart( void )
2949 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2951 name = PRVM_G_STRING( OFS_PARM0 );
2952 VM_CheckEmptyString( name );
2954 video = CL_GetVideo( name );
2956 CL_RestartVideo( video );
2959 ////////////////////////////////////////
2960 // AltString functions
2961 ////////////////////////////////////////
2964 ========================
2967 float altstr_count(string)
2968 ========================
2970 void VM_altstr_count( void )
2972 const char *altstr, *pos;
2975 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2977 altstr = PRVM_G_STRING( OFS_PARM0 );
2978 //VM_CheckEmptyString( altstr );
2980 for( count = 0, pos = altstr ; *pos ; pos++ ) {
2981 if( *pos == '\\' ) {
2985 } else if( *pos == '\'' ) {
2990 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2994 ========================
2997 string altstr_prepare(string)
2998 ========================
3000 void VM_altstr_prepare( void )
3003 const char *instr, *in;
3006 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3008 instr = PRVM_G_STRING( OFS_PARM0 );
3009 //VM_CheckEmptyString( instr );
3010 outstr = VM_GetTempString();
3012 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3021 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3025 ========================
3028 string altstr_get(string, float)
3029 ========================
3031 void VM_altstr_get( void )
3033 const char *altstr, *pos;
3037 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3039 altstr = PRVM_G_STRING( OFS_PARM0 );
3040 //VM_CheckEmptyString( altstr );
3042 count = PRVM_G_FLOAT( OFS_PARM1 );
3043 count = count * 2 + 1;
3045 for( pos = altstr ; *pos && count ; pos++ )
3046 if( *pos == '\\' ) {
3049 } else if( *pos == '\'' )
3053 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
3057 outstr = VM_GetTempString();
3058 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3059 if( *pos == '\\' ) {
3064 } else if( *pos == '\'' )
3070 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3074 ========================
3077 string altstr_set(string altstr, float num, string set)
3078 ========================
3080 void VM_altstr_set( void )
3083 const char *altstr, *str;
3087 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3089 altstr = PRVM_G_STRING( OFS_PARM0 );
3090 //VM_CheckEmptyString( altstr );
3092 num = PRVM_G_FLOAT( OFS_PARM1 );
3094 str = PRVM_G_STRING( OFS_PARM2 );
3095 //VM_CheckEmptyString( str );
3097 outstr = out = VM_GetTempString();
3098 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3103 } else if( *in == '\'' ) {
3108 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( altstr );
3112 for( ; *str; *out++ = *str++ );
3113 // now jump over the old content
3115 if( *in == '\'' || (*in == '\\' && !*++in) )
3119 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
3124 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3128 ========================
3131 string altstr_ins(string altstr, float num, string set)
3132 ========================
3134 void VM_altstr_ins(void)
3144 in = instr = PRVM_G_STRING( OFS_PARM0 );
3145 num = PRVM_G_FLOAT( OFS_PARM1 );
3146 set = setstr = PRVM_G_STRING( OFS_PARM2 );
3148 out = outstr = VM_GetTempString();
3149 for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
3154 } else if( *in == '\'' ) {
3159 for( ; *set ; *out++ = *set++ );
3163 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3166 void VM_Cmd_Init(void)
3168 // only init the stuff for the current prog
3173 void VM_Cmd_Reset(void)
3175 CL_PurgeOwner( MENUOWNER );
3177 VM_Files_CloseAll();
3180 //============================================================================
3183 char *vm_sv_extensions =
3186 prvm_builtin_t vm_sv_builtins[] = {
3187 0 // to be consistent with the old vm
3190 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3192 void VM_SV_Cmd_Init(void)
3196 void VM_SV_Cmd_Reset(void)
3200 //============================================================================
3203 char *vm_cl_extensions =
3206 prvm_builtin_t vm_cl_builtins[] = {
3207 0 // to be consistent with the old vm
3210 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3212 void VM_CL_Cmd_Init(void)
3216 void VM_CL_Cmd_Reset(void)
3220 //============================================================================
3223 char *vm_m_extensions =
3230 setmousetarget(float target)
3233 void VM_M_setmousetarget(void)
3235 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3237 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3240 in_client_mouse = false;
3243 in_client_mouse = true;
3246 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3254 float getmousetarget
3257 void VM_M_getmousetarget(void)
3259 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3262 PRVM_G_FLOAT(OFS_RETURN) = 2;
3264 PRVM_G_FLOAT(OFS_RETURN) = 1;
3273 setkeydest(float dest)
3276 void VM_M_setkeydest(void)
3278 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3280 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3284 key_dest = key_game;
3288 key_dest = key_menu;
3292 // key_dest = key_message
3295 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3306 void VM_M_getkeydest(void)
3308 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3310 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3314 PRVM_G_FLOAT(OFS_RETURN) = 0;
3317 PRVM_G_FLOAT(OFS_RETURN) = 2;
3321 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3324 PRVM_G_FLOAT(OFS_RETURN) = 3;
3332 callfunction(...,string function_name)
3336 mfunction_t *PRVM_ED_FindFunction (const char *name);
3337 void VM_M_callfunction(void)
3343 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3345 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3348 PRVM_ERROR("VM_M_callfunction: null string !\n");
3350 VM_CheckEmptyString(s);
3352 func = PRVM_ED_FindFunction(s);
3355 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3356 else if (func->first_statement < 0)
3358 // negative statements are built in functions
3359 int builtinnumber = -func->first_statement;
3360 prog->xfunction->builtinsprofile++;
3361 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3362 prog->builtins[builtinnumber]();
3364 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3369 PRVM_ExecuteProgram(func - prog->functions,"");
3378 float isfunction(string function_name)
3381 mfunction_t *PRVM_ED_FindFunction (const char *name);
3382 void VM_M_isfunction(void)
3387 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3389 s = PRVM_G_STRING(OFS_PARM0);
3392 PRVM_ERROR("VM_M_isfunction: null string !\n");
3394 VM_CheckEmptyString(s);
3396 func = PRVM_ED_FindFunction(s);
3399 PRVM_G_FLOAT(OFS_RETURN) = false;
3401 PRVM_G_FLOAT(OFS_RETURN) = true;
3408 writetofile(float fhandle, entity ent)
3411 void VM_M_writetofile(void)
3416 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3418 filenum = PRVM_G_FLOAT(OFS_PARM0);
3419 if (filenum < 0 || filenum >= MAX_VMFILES)
3421 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3424 if (VM_FILES[filenum] == NULL)
3426 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3430 ent = PRVM_G_EDICT(OFS_PARM1);
3433 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3437 PRVM_ED_Write (VM_FILES[filenum], ent);
3444 vector getresolution(float number)
3447 extern unsigned short video_resolutions[][2];
3448 void VM_M_getresolution(void)
3451 VM_SAFEPARMCOUNT(1, VM_getresolution);
3453 nr = PRVM_G_FLOAT(OFS_PARM0);
3456 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3457 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3458 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3465 string keynumtostring(float keynum)
3468 void VM_M_keynumtostring(void)
3472 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3474 keynum = PRVM_G_FLOAT(OFS_PARM0);
3476 tmp = VM_GetTempString();
3478 strcpy(tmp, Key_KeynumToString(keynum));
3480 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3487 float stringtokeynum(string key)
3490 void VM_M_stringtokeynum( void )
3493 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3495 str = PRVM_G_STRING( OFS_PARM0 );
3497 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3502 VM_M_findkeysforcommand
3504 string findkeysforcommand(string command)
3506 the returned string is an altstring
3509 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3511 void M_FindKeysForCommand(const char *command, int *keys);
3512 void VM_M_findkeysforcommand(void)
3519 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3521 cmd = PRVM_G_STRING(OFS_PARM0);
3523 VM_CheckEmptyString(cmd);
3525 (ret = VM_GetTempString())[0] = 0;
3527 M_FindKeysForCommand(cmd, keys);
3529 for(i = 0; i < NUMKEYS; i++)
3530 ret = strcat(ret, va(" \'%i\'", keys[i]));
3532 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
3537 VM_M_getserverliststat
3539 float getserverliststat(float type)
3544 0 serverlist_viewcount
3545 1 serverlist_totalcount
3553 void VM_M_getserverliststat( void )
3556 VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
3558 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3560 type = PRVM_G_FLOAT( OFS_PARM0 );
3564 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
3567 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
3569 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3572 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3575 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3578 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3581 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
3584 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
3587 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
3592 ========================
3593 VM_M_resetserverlistmasks
3595 resetserverlistmasks()
3596 ========================
3598 void VM_M_resetserverlistmasks( void )
3600 ServerList_ResetMasks();
3605 ========================
3606 VM_M_setserverlistmaskstring
3608 setserverlistmaskstring(float mask, float fld, string str, float op)
3611 ========================
3613 void VM_M_setserverlistmaskstring( void )
3617 serverlist_mask_t *mask;
3620 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
3621 str = PRVM_G_STRING( OFS_PARM1 );
3623 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
3625 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3626 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3627 mask = &serverlist_andmasks[masknr];
3628 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3629 mask = &serverlist_ormasks[masknr - 512 ];
3631 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
3635 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3639 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3642 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3645 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3648 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3651 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3654 Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
3658 mask->active = true;
3659 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3663 ========================
3664 VM_M_setserverlistmasknumber
3666 setserverlistmasknumber(float mask, float fld, float num, float op)
3670 ========================
3672 void VM_M_setserverlistmasknumber( void )
3675 serverlist_mask_t *mask;
3678 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
3680 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3681 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3682 mask = &serverlist_andmasks[masknr];
3683 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3684 mask = &serverlist_ormasks[masknr - 512 ];
3686 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
3690 number = PRVM_G_FLOAT( OFS_PARM2 );
3691 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3694 case SLIF_MAXPLAYERS:
3695 mask->info.maxplayers = number;
3697 case SLIF_NUMPLAYERS:
3698 mask->info.numplayers = number;
3701 mask->info.ping = number;
3704 mask->info.protocol = number;
3707 Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
3711 mask->active = true;
3712 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3717 ========================
3718 VM_M_resortserverlist
3721 ========================
3723 void VM_M_resortserverlist( void )
3725 ServerList_RebuildViewList();
3730 VM_M_getserverliststring
3732 string getserverliststring(float field, float hostnr)
3735 void VM_M_getserverliststring(void)
3737 serverlist_entry_t *cache;
3740 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3742 PRVM_G_INT(OFS_RETURN) = 0;
3744 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3746 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3748 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3751 cache = serverlist_viewlist[hostnr];
3752 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3754 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
3757 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
3760 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
3763 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
3766 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
3768 // TODO remove this again
3770 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
3773 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
3776 Con_Print("VM_M_getserverliststring: bad field number passed!\n");
3782 VM_M_getserverlistnumber
3784 float getserverlistnumber(float field, float hostnr)
3787 void VM_M_getserverlistnumber(void)
3789 serverlist_entry_t *cache;
3792 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3794 PRVM_G_INT(OFS_RETURN) = 0;
3796 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3798 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3800 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3803 cache = serverlist_viewlist[hostnr];
3804 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3805 case SLIF_MAXPLAYERS:
3806 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3808 case SLIF_NUMPLAYERS:
3809 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3812 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3815 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3818 Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
3823 ========================
3824 VM_M_setserverlistsort
3826 setserverlistsort(float field, float descending)
3827 ========================
3829 void VM_M_setserverlistsort( void )
3831 VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
3833 serverlist_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3834 serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3838 ========================
3839 VM_M_refreshserverlist
3842 ========================
3844 void VM_M_refreshserverlist( void )
3846 VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
3847 ServerList_QueryList();
3851 ========================
3852 VM_M_getserverlistindexforkey
3854 float getserverlistindexforkey(string key)
3855 ========================
3857 void VM_M_getserverlistindexforkey( void )
3860 VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
3862 key = PRVM_G_STRING( OFS_PARM0 );
3863 VM_CheckEmptyString( key );
3865 if( !strcmp( key, "cname" ) )
3866 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
3867 else if( !strcmp( key, "ping" ) )
3868 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
3869 else if( !strcmp( key, "game" ) )
3870 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
3871 else if( !strcmp( key, "mod" ) )
3872 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
3873 else if( !strcmp( key, "map" ) )
3874 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
3875 else if( !strcmp( key, "name" ) )
3876 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
3877 else if( !strcmp( key, "maxplayers" ) )
3878 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
3879 else if( !strcmp( key, "numplayers" ) )
3880 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
3881 else if( !strcmp( key, "protocol" ) )
3882 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
3884 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3888 ========================
3889 VM_M_addwantedserverlistkey
3891 addwantedserverlistkey(string key)
3892 ========================
3894 void VM_M_addwantedserverlistkey( void )
3896 VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
3899 prvm_builtin_t vm_m_builtins[] = {
3900 0, // to be consistent with the old vm
3901 // common builtings (mostly)
3978 VM_search_getfilename, // 77
3982 VM_itof, // isString
3987 VM_altstr_ins, // 86
4001 VM_WriteEntity, // 408
4017 VM_drawresetcliparea,
4018 VM_getimagesize,// 460
4023 VM_cin_restart, // 465
4032 VM_M_setmousetarget,
4033 VM_M_getmousetarget,
4038 VM_M_keynumtostring,
4039 VM_M_findkeysforcommand,// 610
4040 VM_M_getserverliststat,
4041 VM_M_getserverliststring,
4042 VM_M_parseentitydata,
4043 VM_M_stringtokeynum,
4044 VM_M_resetserverlistmasks,
4045 VM_M_setserverlistmaskstring,
4046 VM_M_setserverlistmasknumber,
4047 VM_M_resortserverlist,
4048 VM_M_setserverlistsort,
4049 VM_M_refreshserverlist,
4050 VM_M_getserverlistnumber,
4051 VM_M_getserverlistindexforkey,
4052 VM_M_addwantedserverlistkey // 623
4055 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4057 void VM_M_Cmd_Init(void)
4062 void VM_M_Cmd_Reset(void)