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 == '\\' && !*++pos )
2983 else if( *pos == '\'' )
2986 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2990 ========================
2993 string altstr_prepare(string)
2994 ========================
2996 void VM_altstr_prepare( void )
2999 const char *instr, *in;
3002 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
3004 instr = PRVM_G_STRING( OFS_PARM0 );
3005 //VM_CheckEmptyString( instr );
3006 outstr = VM_GetTempString();
3008 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3017 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3021 ========================
3024 string altstr_get(string, float)
3025 ========================
3027 void VM_altstr_get( void )
3029 const char *altstr, *pos;
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_SetEngineString( NULL );
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_SetEngineString( outstr );
3069 ========================
3072 string altstr_set(string altstr, float num, string set)
3073 ========================
3075 void VM_altstr_set( void )
3078 const char *altstr, *str;
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_SetEngineString( NULL );
3104 for( ; *str; *out++ = *str++ );
3105 // now jump over the old contents
3107 if( *in == '\'' || (*in == '\\' && !*++in) )
3111 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
3116 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3120 ========================
3123 string altstr_ins(string altstr, float num, string set)
3124 ========================
3126 void VM_altstr_ins(void)
3136 in = instr = PRVM_G_STRING( OFS_PARM0 );
3137 num = PRVM_G_FLOAT( OFS_PARM1 );
3138 set = setstr = PRVM_G_STRING( OFS_PARM2 );
3140 out = outstr = VM_GetTempString();
3141 for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
3142 if( *in == '\\' && !*++in )
3144 else if( *in == '\'' )
3147 for( ; *set ; *out++ = *set++ );
3150 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
3153 void VM_Cmd_Init(void)
3155 // only init the stuff for the current prog
3160 void VM_Cmd_Reset(void)
3162 CL_PurgeOwner( MENUOWNER );
3164 VM_Files_CloseAll();
3167 //============================================================================
3170 char *vm_sv_extensions =
3173 prvm_builtin_t vm_sv_builtins[] = {
3174 0 // to be consistent with the old vm
3177 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3179 void VM_SV_Cmd_Init(void)
3183 void VM_SV_Cmd_Reset(void)
3187 //============================================================================
3190 char *vm_cl_extensions =
3193 prvm_builtin_t vm_cl_builtins[] = {
3194 0 // to be consistent with the old vm
3197 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3199 void VM_CL_Cmd_Init(void)
3203 void VM_CL_Cmd_Reset(void)
3207 //============================================================================
3210 char *vm_m_extensions =
3217 setmousetarget(float target)
3220 void VM_M_setmousetarget(void)
3222 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3224 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3227 in_client_mouse = false;
3230 in_client_mouse = true;
3233 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3241 float getmousetarget
3244 void VM_M_getmousetarget(void)
3246 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3249 PRVM_G_FLOAT(OFS_RETURN) = 2;
3251 PRVM_G_FLOAT(OFS_RETURN) = 1;
3260 setkeydest(float dest)
3263 void VM_M_setkeydest(void)
3265 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3267 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3271 key_dest = key_game;
3275 key_dest = key_menu;
3279 // key_dest = key_message
3282 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3293 void VM_M_getkeydest(void)
3295 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3297 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3301 PRVM_G_FLOAT(OFS_RETURN) = 0;
3304 PRVM_G_FLOAT(OFS_RETURN) = 2;
3308 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3311 PRVM_G_FLOAT(OFS_RETURN) = 3;
3319 callfunction(...,string function_name)
3323 mfunction_t *PRVM_ED_FindFunction (const char *name);
3324 void VM_M_callfunction(void)
3330 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3332 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3335 PRVM_ERROR("VM_M_callfunction: null string !\n");
3337 VM_CheckEmptyString(s);
3339 func = PRVM_ED_FindFunction(s);
3342 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3343 else if (func->first_statement < 0)
3345 // negative statements are built in functions
3346 int builtinnumber = -func->first_statement;
3347 prog->xfunction->builtinsprofile++;
3348 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3349 prog->builtins[builtinnumber]();
3351 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3356 PRVM_ExecuteProgram(func - prog->functions,"");
3365 float isfunction(string function_name)
3368 mfunction_t *PRVM_ED_FindFunction (const char *name);
3369 void VM_M_isfunction(void)
3374 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3376 s = PRVM_G_STRING(OFS_PARM0);
3379 PRVM_ERROR("VM_M_isfunction: null string !\n");
3381 VM_CheckEmptyString(s);
3383 func = PRVM_ED_FindFunction(s);
3386 PRVM_G_FLOAT(OFS_RETURN) = false;
3388 PRVM_G_FLOAT(OFS_RETURN) = true;
3395 writetofile(float fhandle, entity ent)
3398 void VM_M_writetofile(void)
3403 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3405 filenum = PRVM_G_FLOAT(OFS_PARM0);
3406 if (filenum < 0 || filenum >= MAX_VMFILES)
3408 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3411 if (VM_FILES[filenum] == NULL)
3413 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3417 ent = PRVM_G_EDICT(OFS_PARM1);
3420 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3424 PRVM_ED_Write (VM_FILES[filenum], ent);
3431 vector getresolution(float number)
3434 extern unsigned short video_resolutions[][2];
3435 void VM_M_getresolution(void)
3438 VM_SAFEPARMCOUNT(1, VM_getresolution);
3440 nr = PRVM_G_FLOAT(OFS_PARM0);
3443 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3444 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3445 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3452 string keynumtostring(float keynum)
3455 void VM_M_keynumtostring(void)
3459 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3461 keynum = PRVM_G_FLOAT(OFS_PARM0);
3463 tmp = VM_GetTempString();
3465 strcpy(tmp, Key_KeynumToString(keynum));
3467 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3474 float stringtokeynum(string key)
3477 void VM_M_stringtokeynum( void )
3480 VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
3482 str = PRVM_G_STRING( OFS_PARM0 );
3484 PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
3489 VM_M_findkeysforcommand
3491 string findkeysforcommand(string command)
3493 the returned string is an altstring
3496 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3498 void M_FindKeysForCommand(const char *command, int *keys);
3499 void VM_M_findkeysforcommand(void)
3506 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3508 cmd = PRVM_G_STRING(OFS_PARM0);
3510 VM_CheckEmptyString(cmd);
3512 (ret = VM_GetTempString())[0] = 0;
3514 M_FindKeysForCommand(cmd, keys);
3516 for(i = 0; i < NUMKEYS; i++)
3517 ret = strcat(ret, va(" \'%i\'", keys[i]));
3519 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
3524 VM_M_getserverliststat
3526 float getserverliststat(float type)
3531 0 serverlist_viewcount
3532 1 serverlist_totalcount
3540 void VM_M_getserverliststat( void )
3543 VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
3545 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3547 type = PRVM_G_FLOAT( OFS_PARM0 );
3551 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
3554 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
3556 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3559 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3562 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3565 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3568 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
3571 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
3574 Con_Printf( "VM_M_getserverliststat: bad type %i!\n", type );
3579 ========================
3580 VM_M_resetserverlistmasks
3582 resetserverlistmasks()
3583 ========================
3585 void VM_M_resetserverlistmasks( void )
3587 ServerList_ResetMasks();
3592 ========================
3593 VM_M_setserverlistmaskstring
3595 setserverlistmaskstring(float mask, float fld, string str, float op)
3598 ========================
3600 void VM_M_setserverlistmaskstring( void )
3604 serverlist_mask_t *mask;
3607 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
3608 str = PRVM_G_STRING( OFS_PARM1 );
3610 PRVM_ERROR( "VM_M_setserverlistmaskstring: null string passed!" );
3612 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3613 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3614 mask = &serverlist_andmasks[masknr];
3615 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3616 mask = &serverlist_ormasks[masknr - 512 ];
3618 Con_Printf( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
3622 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3626 strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
3629 strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name) );
3632 strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map) );
3635 strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod) );
3638 strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game) );
3641 Con_Printf( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
3645 mask->active = true;
3646 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3650 ========================
3651 VM_M_setserverlistmasknumber
3653 setserverlistmasknumber(float mask, float fld, float num, float op)
3657 ========================
3659 void VM_M_setserverlistmasknumber( void )
3662 serverlist_mask_t *mask;
3665 VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
3667 masknr = PRVM_G_FLOAT( OFS_PARM0 );
3668 if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
3669 mask = &serverlist_andmasks[masknr];
3670 else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
3671 mask = &serverlist_ormasks[masknr - 512 ];
3673 Con_Printf( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
3677 number = PRVM_G_FLOAT( OFS_PARM2 );
3678 field = (int) PRVM_G_FLOAT( OFS_PARM1 );
3681 case SLIF_MAXPLAYERS:
3682 mask->info.maxplayers = number;
3684 case SLIF_NUMPLAYERS:
3685 mask->info.numplayers = number;
3688 mask->info.ping = number;
3691 mask->info.protocol = number;
3694 Con_Printf( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
3698 mask->active = true;
3699 mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
3704 ========================
3705 VM_M_resortserverlist
3708 ========================
3710 void VM_M_resortserverlist( void )
3712 ServerList_RebuildViewList();
3717 VM_M_getserverliststring
3719 string getserverliststring(float field, float hostnr)
3722 void VM_M_getserverliststring(void)
3724 serverlist_entry_t *cache;
3727 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3729 PRVM_G_INT(OFS_RETURN) = 0;
3731 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3733 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3735 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3738 cache = serverlist_viewlist[hostnr];
3739 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3741 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
3744 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
3747 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
3750 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
3753 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
3755 // TODO remove this again
3757 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
3760 PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
3763 Con_Print("VM_M_getserverliststring: bad field number passed!\n");
3769 VM_M_getserverlistnumber
3771 float getserverlistnumber(float field, float hostnr)
3774 void VM_M_getserverlistnumber(void)
3776 serverlist_entry_t *cache;
3779 VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
3781 PRVM_G_INT(OFS_RETURN) = 0;
3783 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3785 if(hostnr < 0 || hostnr >= serverlist_viewcount)
3787 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
3790 cache = serverlist_viewlist[hostnr];
3791 switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
3792 case SLIF_MAXPLAYERS:
3793 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
3795 case SLIF_NUMPLAYERS:
3796 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
3799 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
3802 PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
3805 Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
3810 ========================
3811 VM_M_setserverlistsort
3813 setserverlistsort(float field, float descending)
3814 ========================
3816 void VM_M_setserverlistsort( void )
3818 VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
3820 serverlist_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
3821 serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
3825 ========================
3826 VM_M_refreshserverlist
3829 ========================
3831 void VM_M_refreshserverlist( void )
3833 VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
3834 ServerList_QueryList();
3838 ========================
3839 VM_M_getserverlistindexforkey
3841 float getserverlistindexforkey(string key)
3842 ========================
3844 void VM_M_getserverlistindexforkey( void )
3847 VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
3849 key = PRVM_G_STRING( OFS_PARM0 );
3850 VM_CheckEmptyString( key );
3852 if( !strcmp( key, "cname" ) )
3853 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
3854 else if( !strcmp( key, "ping" ) )
3855 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
3856 else if( !strcmp( key, "game" ) )
3857 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
3858 else if( !strcmp( key, "mod" ) )
3859 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
3860 else if( !strcmp( key, "map" ) )
3861 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
3862 else if( !strcmp( key, "name" ) )
3863 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
3864 else if( !strcmp( key, "maxplayers" ) )
3865 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
3866 else if( !strcmp( key, "numplayers" ) )
3867 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
3868 else if( !strcmp( key, "protocol" ) )
3869 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
3871 PRVM_G_FLOAT( OFS_RETURN ) = -1;
3875 ========================
3876 VM_M_addwantedserverlistkey
3878 addwantedserverlistkey(string key)
3879 ========================
3881 void VM_M_addwantedserverlistkey( void )
3883 VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
3886 prvm_builtin_t vm_m_builtins[] = {
3887 0, // to be consistent with the old vm
3888 // common builtings (mostly)
3965 VM_search_getfilename, // 77
3969 VM_itof, // isString
3974 VM_altstr_ins, // 86
3988 VM_WriteEntity, // 408
4004 VM_drawresetcliparea,
4005 VM_getimagesize,// 460
4010 VM_cin_restart, // 465
4019 VM_M_setmousetarget,
4020 VM_M_getmousetarget,
4025 VM_M_keynumtostring,
4026 VM_M_findkeysforcommand,// 610
4027 VM_M_getserverliststat,
4028 VM_M_getserverliststring,
4029 VM_M_parseentitydata,
4030 VM_M_stringtokeynum,
4031 VM_M_resetserverlistmasks,
4032 VM_M_setserverlistmaskstring,
4033 VM_M_setserverlistmasknumber,
4034 VM_M_resortserverlist,
4035 VM_M_setserverlistsort,
4036 VM_M_refreshserverlist,
4037 VM_M_getserverlistnumber,
4038 VM_M_getserverlistindexforkey,
4039 VM_M_addwantedserverlistkey // 623
4042 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
4044 void VM_M_Cmd_Init(void)
4049 void VM_M_Cmd_Reset(void)