2 // Basically every vm builtin cmd should be in here.
3 // All 3 builtin and extension lists can be found here
4 // cause large (I think they will) parts are from pr_cmds the same copyright like in pr_cmds
9 ============================================================================
13 checkextension(string)
18 sprint(float clientnum,...[string])
19 centerprint(...[string])
20 vector normalize(vector)
22 float vectoyaw(vector)
23 vector vectoangles(vector)
27 cvar_set (string,string)
33 float stof(...[string])
36 entity find(entity start, .string field, string match)
38 entity findfloat(entity start, .float field, float match)
39 entity findentity(entity start, .entity field, entity match)
41 entity findchain(.string field, string match)
43 entity findchainfloat(.string field, float match)
44 entity findchainentity(.string field, entity match)
46 string precache_file(string)
47 string precache_sound (string sample)
55 entity nextent(entity)
60 float registercvar (string name, string value, float flags)
61 float min(float a, float b, ...[float])
62 float max(float a, float b, ...[float])
63 float bound(float min, float value, float max)
64 float pow(float a, float b)
65 copyentity(entity src, entity dst)
66 float fopen(string filename, float mode)
68 string fgets(float fhandle)
69 fputs(float fhandle, string s)
70 float strlen(string s)
71 string strcat(string,string,...[string])
72 string substring(string s, float start, float length)
74 string strzone(string s)
76 float tokenize(string s)
81 clientcommand(float client, string s) (for client and menu)
82 changelevel(string map)
83 localsound(string sample)
86 loadfromdata(string data)
87 loadfromfile(string file)
88 float mod(float val, float m)
89 const string str_cvar (string)
93 float search_begin(string pattern, float caseinsensitive, float quiet)
94 void search_end(float handle)
95 float search_getsize(float handle)
96 string search_getfilename(float handle, float num)
98 string chr(float ascii)
103 float altstr_count(string)
104 string altstr_prepare(string)
105 string altstr_get(string,float)
106 string altstr_set(string altstr, float num, string set)
108 perhaps only : Menu : WriteMsg
109 ===============================
111 WriteByte(float data, float dest, float desto)
112 WriteChar(float data, float dest, float desto)
113 WriteShort(float data, float dest, float desto)
114 WriteLong(float data, float dest, float desto)
115 WriteAngle(float data, float dest, float desto)
116 WriteCoord(float data, float dest, float desto)
117 WriteString(string data, float dest, float desto)
118 WriteEntity(entity data, float dest, float desto)
120 Client & Menu : draw functions & video functions
121 ===================================================
123 float iscachedpic(string pic)
124 string precache_pic(string pic)
126 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
127 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
128 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
129 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
130 drawsetcliparea(float x, float y, float width, float height)
132 vector getimagesize(string pic)
134 float cin_open(string file, string name)
135 void cin_close(string name)
136 void cin_setstate(string name, float type)
137 float cin_getstate(string name)
138 void cin_restart(string name)
140 ==============================================================================
144 setkeydest(float dest)
146 setmousetarget(float target)
147 float getmousetarget(void)
149 callfunction(...,string function_name)
150 writetofile(float fhandle, entity ent)
151 float isfunction(string function_name)
152 vector getresolution(float number)
153 string keynumtostring(float keynum)
154 string findkeysforcommand(string command)
155 float gethostcachestat(float type)
156 string gethostcachestring(float type, float hostnr)
158 parseentitydata(entity ent, string data)
161 #include "quakedef.h"
162 #include "progdefs.h"
164 #include "clprogdefs.h"
165 #include "mprogdefs.h"
167 #include "cl_video.h"
169 //============================================================================
170 // nice helper macros
172 #ifndef VM_NOPARMCHECK
173 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
175 #define VM_SAFEPARMCOUNT(p,f)
178 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
180 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
182 #define e10 0,0,0,0,0,0,0,0,0,0
183 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
184 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
186 //============================================================================
189 // string zone mempool
190 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
192 // temp string handling
193 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
194 #define VM_STRINGTEMP_BUFFERS 16
195 #define VM_STRINGTEMP_LENGTH 4096
196 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
197 static int vm_string_tempindex = 0;
200 #define MAX_VMFILES 256
201 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
202 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
204 qfile_t *vm_files[MAX_PRVMFILES];
206 // qc fs search handling
207 #define MAX_VMSEARCHES 128
208 #define TOTAL_VMSEARCHES MAX_VMSEARCHES * PRVM_MAXPROGS
209 #define VM_SEARCHLIST ((fssearch_t**)(vm_fssearchlist + PRVM_GetProgNr() * MAX_VMSEARCHES))
211 fssearch_t *vm_fssearchlist[TOTAL_VMSEARCHES];
213 static char *VM_GetTempString(void)
216 s = vm_string_temp[vm_string_tempindex];
217 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
221 void VM_CheckEmptyString (char *s)
224 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
227 //============================================================================
230 void VM_VarString(int first, char *out, int outlength)
236 outend = out + outlength - 1;
237 for (i = first;i < prog->argc && out < outend;i++)
239 s = PRVM_G_STRING((OFS_PARM0+i*3));
240 while (out < outend && *s)
250 returns true if the extension is supported by the server
252 checkextension(extensionname)
256 // kind of helper function
257 static qboolean checkextension(char *name)
263 for (e = prog->extensionstring;*e;e++)
270 while (*e && *e != ' ')
272 if (e - start == len)
273 if (!strncasecmp(start, name, len))
281 void VM_checkextension (void)
283 VM_SAFEPARMCOUNT(1,VM_checkextension);
285 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
292 This is a TERMINAL error, which will kill off the entire prog.
301 char string[VM_STRINGTEMP_LENGTH];
303 VM_VarString(0, string, sizeof(string));
304 Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
307 ed = PRVM_G_EDICT(prog->self->ofs);
311 PRVM_ERROR ("%s: Program error", PRVM_NAME);
318 Dumps out self, then an error message. The program is aborted and self is
319 removed, but the level can continue.
324 void VM_objerror (void)
327 char string[VM_STRINGTEMP_LENGTH];
329 VM_VarString(0, string, sizeof(string));
330 Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
333 ed = PRVM_G_EDICT (prog->self->ofs);
339 // objerror has to display the object fields -> else call
340 PRVM_ERROR ("VM_objecterror: self not defined !\n");
345 VM_print (actually used only by client and menu)
354 char string[VM_STRINGTEMP_LENGTH];
356 VM_VarString(0, string, sizeof(string));
364 broadcast print to everyone on server
369 void VM_bprint (void)
371 char string[VM_STRINGTEMP_LENGTH];
375 Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
379 VM_VarString(0, string, sizeof(string));
380 SV_BroadcastPrint(string);
385 VM_sprint (menu & client but only if server.active == true)
387 single print to a specific client
389 sprint(float clientnum,...[string])
392 void VM_sprint (void)
396 char string[VM_STRINGTEMP_LENGTH];
398 //find client for this entity
399 clientnum = PRVM_G_FLOAT(OFS_PARM0);
400 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
402 Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
406 client = svs.clients + clientnum;
407 VM_VarString(1, string, sizeof(string));
408 MSG_WriteChar(&client->message,svc_print);
409 MSG_WriteString(&client->message, string);
416 single print to the screen
418 centerprint(clientent, value)
421 void VM_centerprint (void)
423 char string[VM_STRINGTEMP_LENGTH];
425 VM_VarString(0, string, sizeof(string));
426 SCR_CenterPrint(string);
433 vector normalize(vector)
436 void VM_normalize (void)
442 VM_SAFEPARMCOUNT(1,VM_normalize);
444 value1 = PRVM_G_VECTOR(OFS_PARM0);
446 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
450 newvalue[0] = newvalue[1] = newvalue[2] = 0;
454 newvalue[0] = value1[0] * new;
455 newvalue[1] = value1[1] * new;
456 newvalue[2] = value1[2] * new;
459 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
474 VM_SAFEPARMCOUNT(1,VM_vlen);
476 value1 = PRVM_G_VECTOR(OFS_PARM0);
478 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
481 PRVM_G_FLOAT(OFS_RETURN) = new;
488 float vectoyaw(vector)
491 void VM_vectoyaw (void)
496 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
498 value1 = PRVM_G_VECTOR(OFS_PARM0);
500 if (value1[1] == 0 && value1[0] == 0)
504 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
509 PRVM_G_FLOAT(OFS_RETURN) = yaw;
517 vector vectoangles(vector)
520 void VM_vectoangles (void)
526 VM_SAFEPARMCOUNT(1,VM_vectoangles);
528 value1 = PRVM_G_VECTOR(OFS_PARM0);
530 if (value1[1] == 0 && value1[0] == 0)
540 // LordHavoc: optimized a bit
543 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
547 else if (value1[1] > 0)
552 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
553 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
558 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
559 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
560 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
567 Returns a number from 0<= num < 1
572 void VM_random (void)
574 VM_SAFEPARMCOUNT(0,VM_random);
576 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
583 Each entity can have eight independant sound sources, like voice,
586 Channel 0 is an auto-allocate channel, the others override anything
587 already running on that entity/channel pair.
589 An attenuation of 0 will play full volume everywhere in the level.
590 Larger attenuations will drop off.
603 entity = G_EDICT(OFS_PARM0);
604 channel = G_FLOAT(OFS_PARM1);
605 sample = G_STRING(OFS_PARM2);
606 volume = G_FLOAT(OFS_PARM3) * 255;
607 attenuation = G_FLOAT(OFS_PARM4);
609 if (volume < 0 || volume > 255)
610 Host_Error ("SV_StartSound: volume = %i", volume);
612 if (attenuation < 0 || attenuation > 4)
613 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
615 if (channel < 0 || channel > 7)
616 Host_Error ("SV_StartSound: channel = %i", channel);
618 SV_StartSound (entity, channel, sample, volume, attenuation);
626 localsound(string sample)
629 void VM_localsound(void)
633 VM_SAFEPARMCOUNT(1,VM_localsound);
635 s = PRVM_G_STRING(OFS_PARM0);
637 if(!S_LocalSound (s))
639 Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
640 PRVM_G_FLOAT(OFS_RETURN) = -4;
644 PRVM_G_FLOAT(OFS_RETURN) = 1;
656 PRVM_ERROR ("%s: break statement", PRVM_NAME);
659 //============================================================================
665 Sends text over to the client's execution buffer
667 [localcmd (string) or]
671 void VM_localcmd (void)
673 VM_SAFEPARMCOUNT(1,VM_localcmd);
675 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
687 VM_SAFEPARMCOUNT(1,VM_cvar);
689 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
696 const string str_cvar (string)
699 void VM_str_cvar(void)
702 const char *cvar_string;
703 VM_SAFEPARMCOUNT(1,VM_str_cvar);
705 name = PRVM_G_STRING(OFS_PARM0);
708 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
710 VM_CheckEmptyString(name);
712 out = VM_GetTempString();
714 cvar_string = Cvar_VariableString(name);
716 strcpy(out, cvar_string);
718 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
725 void cvar_set (string,string)
728 void VM_cvar_set (void)
730 VM_SAFEPARMCOUNT(2,VM_cvar_set);
732 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
742 void VM_dprint (void)
744 char string[VM_STRINGTEMP_LENGTH];
745 if (developer.integer)
747 VM_VarString(0, string, sizeof(string));
748 Con_Printf("%s: %s", PRVM_NAME, string);
765 VM_SAFEPARMCOUNT(1, VM_ftos);
767 v = PRVM_G_FLOAT(OFS_PARM0);
769 s = VM_GetTempString();
770 if ((float)((int)v) == v)
771 sprintf(s, "%i", (int)v);
774 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
789 VM_SAFEPARMCOUNT(1,VM_fabs);
791 v = PRVM_G_FLOAT(OFS_PARM0);
792 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
807 VM_SAFEPARMCOUNT(1,VM_vtos);
809 s = VM_GetTempString();
810 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]);
811 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
826 VM_SAFEPARMCOUNT(1, VM_etos);
828 s = VM_GetTempString();
829 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
830 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
837 float stof(...[string])
842 char string[VM_STRINGTEMP_LENGTH];
843 VM_VarString(0, string, sizeof(string));
844 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
848 ========================
852 ========================
856 VM_SAFEPARMCOUNT(1, VM_itof);
857 PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
861 ========================
865 ========================
870 VM_SAFEPARMCOUNT(1, VM_ftoi);
872 ent = PRVM_G_FLOAT(OFS_PARM0);
873 if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
874 PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
876 PRVM_G_INT(OFS_RETURN) = ent;
890 prog->xfunction->builtinsprofile += 20;
891 ed = PRVM_ED_Alloc();
903 void VM_remove (void)
906 prog->xfunction->builtinsprofile += 20;
908 VM_SAFEPARMCOUNT(1, VM_remove);
910 ed = PRVM_G_EDICT(OFS_PARM0);
911 // if (ed == prog->edicts)
912 // PRVM_ERROR ("remove: tried to remove world\n");
913 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
914 // Host_Error("remove: tried to remove a client\n");
922 entity find(entity start, .string field, string match)
933 VM_SAFEPARMCOUNT(3,VM_find);
935 e = PRVM_G_EDICTNUM(OFS_PARM0);
936 f = PRVM_G_INT(OFS_PARM1);
937 s = PRVM_G_STRING(OFS_PARM2);
941 // return reserved edict 0 (could be used for whatever the prog wants)
942 VM_RETURN_EDICT(prog->edicts);
946 for (e++ ; e < prog->num_edicts ; e++)
948 prog->xfunction->builtinsprofile++;
949 ed = PRVM_EDICT_NUM(e);
952 t = PRVM_E_STRING(ed,f);
962 VM_RETURN_EDICT(prog->edicts);
969 entity findfloat(entity start, .float field, float match)
970 entity findentity(entity start, .entity field, entity match)
973 // LordHavoc: added this for searching float, int, and entity reference fields
974 void VM_findfloat (void)
981 VM_SAFEPARMCOUNT(3,VM_findfloat);
983 e = PRVM_G_EDICTNUM(OFS_PARM0);
984 f = PRVM_G_INT(OFS_PARM1);
985 s = PRVM_G_FLOAT(OFS_PARM2);
987 for (e++ ; e < prog->num_edicts ; e++)
989 prog->xfunction->builtinsprofile++;
990 ed = PRVM_EDICT_NUM(e);
993 if (PRVM_E_FLOAT(ed,f) == s)
1000 VM_RETURN_EDICT(prog->edicts);
1007 entity findchain(.string field, string match)
1010 int PRVM_ED_FindFieldOffset(const char *field);
1011 // chained search for strings in entity fields
1012 // entity(.string field, string match) findchain = #402;
1013 void VM_findchain (void)
1019 prvm_edict_t *ent, *chain;
1021 VM_SAFEPARMCOUNT(2,VM_findchain);
1023 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
1024 if(!prog->flag & PRVM_FE_CHAIN)
1025 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1027 chain_of = PRVM_ED_FindFieldOffset ("chain");
1029 chain = prog->edicts;
1031 f = PRVM_G_INT(OFS_PARM0);
1032 s = PRVM_G_STRING(OFS_PARM1);
1035 VM_RETURN_EDICT(prog->edicts);
1039 ent = PRVM_NEXT_EDICT(prog->edicts);
1040 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1042 prog->xfunction->builtinsprofile++;
1045 t = PRVM_E_STRING(ent,f);
1051 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1055 VM_RETURN_EDICT(chain);
1062 entity findchainfloat(.string field, float match)
1063 entity findchainentity(.string field, entity match)
1066 // LordHavoc: chained search for float, int, and entity reference fields
1067 // entity(.string field, float match) findchainfloat = #403;
1068 void VM_findchainfloat (void)
1074 prvm_edict_t *ent, *chain;
1076 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1078 if(!prog->flag & PRVM_FE_CHAIN)
1079 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1081 chain_of = PRVM_ED_FindFieldOffset ("chain");
1083 chain = (prvm_edict_t *)prog->edicts;
1085 f = PRVM_G_INT(OFS_PARM0);
1086 s = PRVM_G_FLOAT(OFS_PARM1);
1088 ent = PRVM_NEXT_EDICT(prog->edicts);
1089 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1091 prog->xfunction->builtinsprofile++;
1094 if (PRVM_E_FLOAT(ent,f) != s)
1097 PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
1101 VM_RETURN_EDICT(chain);
1108 string precache_file(string)
1111 void VM_precache_file (void)
1112 { // precache_file is only used to copy files with qcc, it does nothing
1113 VM_SAFEPARMCOUNT(1,VM_precache_file);
1115 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1122 used instead of the other VM_precache_* functions in the builtin list
1126 void VM_precache_error (void)
1128 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1135 string precache_sound (string sample)
1138 void VM_precache_sound (void)
1142 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1144 s = PRVM_G_STRING(OFS_PARM0);
1145 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1146 VM_CheckEmptyString (s);
1148 if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
1149 Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1159 void VM_coredump (void)
1161 VM_SAFEPARMCOUNT(0,VM_coredump);
1163 Cbuf_AddText("prvm_edicts ");
1164 Cbuf_AddText(PRVM_NAME);
1175 void PRVM_StackTrace(void);
1176 void VM_stackdump (void)
1178 VM_SAFEPARMCOUNT(0, VM_stackdump);
1193 VM_SAFEPARMCOUNT(0, VM_crash);
1195 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1205 void VM_traceon (void)
1207 VM_SAFEPARMCOUNT(0,VM_traceon);
1219 void VM_traceoff (void)
1221 VM_SAFEPARMCOUNT(0,VM_traceoff);
1223 prog->trace = false;
1233 void VM_eprint (void)
1235 VM_SAFEPARMCOUNT(1,VM_eprint);
1237 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1251 VM_SAFEPARMCOUNT(1,VM_rint);
1253 f = PRVM_G_FLOAT(OFS_PARM0);
1255 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1257 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1267 void VM_floor (void)
1269 VM_SAFEPARMCOUNT(1,VM_floor);
1271 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1283 VM_SAFEPARMCOUNT(1,VM_ceil);
1285 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1293 entity nextent(entity)
1296 void VM_nextent (void)
1301 i = PRVM_G_EDICTNUM(OFS_PARM0);
1304 prog->xfunction->builtinsprofile++;
1306 if (i == prog->num_edicts)
1308 VM_RETURN_EDICT(prog->edicts);
1311 ent = PRVM_EDICT_NUM(i);
1312 if (!ent->p.e->free)
1314 VM_RETURN_EDICT(ent);
1321 ===============================================================================
1324 used only for client and menu
1325 severs uses VM_SV_...
1327 Write*(* data, float type, float to)
1329 ===============================================================================
1332 #define MSG_BROADCAST 0 // unreliable to all
1333 #define MSG_ONE 1 // reliable to one (msg_entity)
1334 #define MSG_ALL 2 // reliable to all
1335 #define MSG_INIT 3 // write to the init string
1337 sizebuf_t *VM_WriteDest (void)
1343 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1345 dest = G_FLOAT(OFS_PARM1);
1349 return &sv.datagram;
1352 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1353 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1354 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1356 return &svs.clients[destclient].message;
1359 return &sv.reliable_datagram;
1365 PRVM_ERROR ("WriteDest: bad destination");
1372 void VM_WriteByte (void)
1374 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1377 void VM_WriteChar (void)
1379 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1382 void VM_WriteShort (void)
1384 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1387 void VM_WriteLong (void)
1389 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1392 void VM_WriteAngle (void)
1394 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1397 void VM_WriteCoord (void)
1399 MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
1402 void VM_WriteString (void)
1404 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1407 void VM_WriteEntity (void)
1409 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1412 //=============================================================================
1419 changelevel(string map)
1422 void VM_changelevel (void)
1426 VM_SAFEPARMCOUNT(1, VM_changelevel);
1430 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1434 // make sure we don't issue two changelevels
1435 if (svs.changelevel_issued)
1437 svs.changelevel_issued = true;
1439 s = G_STRING(OFS_PARM0);
1440 Cbuf_AddText (va("changelevel %s\n",s));
1452 VM_SAFEPARMCOUNT(1,VM_sin);
1453 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1464 VM_SAFEPARMCOUNT(1,VM_cos);
1465 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1477 VM_SAFEPARMCOUNT(1,VM_sqrt);
1478 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1485 Returns a vector of length < 1 and > 0
1490 void VM_randomvec (void)
1495 VM_SAFEPARMCOUNT(0, VM_randomvec);
1500 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1501 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1502 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1504 while (DotProduct(temp, temp) >= 1);
1505 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1508 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1509 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1510 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1511 // length returned always > 0
1512 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1513 VectorScale(temp,length, temp);*/
1514 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1517 //=============================================================================
1523 float registercvar (string name, string value, float flags)
1526 void VM_registercvar (void)
1531 VM_SAFEPARMCOUNT(3,VM_registercvar);
1533 name = PRVM_G_STRING(OFS_PARM0);
1534 value = PRVM_G_STRING(OFS_PARM1);
1535 flags = PRVM_G_FLOAT(OFS_PARM2);
1536 PRVM_G_FLOAT(OFS_RETURN) = 0;
1538 if(flags > CVAR_MAXFLAGSVAL)
1541 // first check to see if it has already been defined
1542 if (Cvar_FindVar (name))
1545 // check for overlap with a command
1546 if (Cmd_Exists (name))
1548 Con_Printf("VM_registercvar: %s is a command\n", name);
1552 Cvar_Get(name, value, flags);
1554 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1561 returns the minimum of two supplied floats
1563 float min(float a, float b, ...[float])
1568 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1569 if (prog->argc == 2)
1570 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1571 else if (prog->argc >= 3)
1574 float f = PRVM_G_FLOAT(OFS_PARM0);
1575 for (i = 1;i < prog->argc;i++)
1576 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1577 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1578 PRVM_G_FLOAT(OFS_RETURN) = f;
1581 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1588 returns the maximum of two supplied floats
1590 float max(float a, float b, ...[float])
1595 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1596 if (prog->argc == 2)
1597 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1598 else if (prog->argc >= 3)
1601 float f = PRVM_G_FLOAT(OFS_PARM0);
1602 for (i = 1;i < prog->argc;i++)
1603 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1604 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1605 PRVM_G_FLOAT(OFS_RETURN) = f;
1608 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1615 returns number bounded by supplied range
1617 float bound(float min, float value, float max)
1620 void VM_bound (void)
1622 VM_SAFEPARMCOUNT(3,VM_bound);
1623 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1630 returns a raised to power b
1632 float pow(float a, float b)
1637 VM_SAFEPARMCOUNT(2,VM_pow);
1638 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1645 copies data from one entity to another
1647 copyentity(entity src, entity dst)
1650 void VM_copyentity (void)
1652 prvm_edict_t *in, *out;
1653 VM_SAFEPARMCOUNT(2,VM_copyentity);
1654 in = PRVM_G_EDICT(OFS_PARM0);
1655 out = PRVM_G_EDICT(OFS_PARM1);
1656 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1663 sets the color of a client and broadcasts the update to all connected clients
1665 setcolor(clientent, value)
1668 /*void PF_setcolor (void)
1674 entnum = G_EDICTNUM(OFS_PARM0);
1675 i = G_FLOAT(OFS_PARM1);
1677 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1679 Con_Print("tried to setcolor a non-client\n");
1683 client = svs.clients + entnum-1;
1684 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1687 client->old_colors = i;
1688 client->edict->v->team = (i & 15) + 1;
1690 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1691 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1692 MSG_WriteByte (&sv.reliable_datagram, i);
1695 void VM_Files_Init(void)
1697 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1700 void VM_Files_CloseAll(void)
1703 for (i = 0;i < MAX_VMFILES;i++)
1706 FS_Close(VM_FILES[i]);
1707 //VM_FILES[i] = NULL;
1709 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1716 float fopen(string filename, float mode)
1719 // float(string filename, float mode) fopen = #110;
1720 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1721 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1725 char *modestring, *filename;
1727 VM_SAFEPARMCOUNT(2,VM_fopen);
1729 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1730 if (VM_FILES[filenum] == NULL)
1732 if (filenum >= MAX_VMFILES)
1734 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1735 PRVM_G_FLOAT(OFS_RETURN) = -2;
1738 mode = PRVM_G_FLOAT(OFS_PARM1);
1741 case 0: // FILE_READ
1744 case 1: // FILE_APPEND
1747 case 2: // FILE_WRITE
1751 Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1752 PRVM_G_FLOAT(OFS_RETURN) = -3;
1755 filename = PRVM_G_STRING(OFS_PARM0);
1756 // .. is parent directory on many platforms
1757 // / is parent directory on Amiga
1758 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1759 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1760 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1762 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1763 PRVM_G_FLOAT(OFS_RETURN) = -4;
1766 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1767 if (VM_FILES[filenum] == NULL && mode == 0)
1768 VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false);
1770 if (VM_FILES[filenum] == NULL)
1771 PRVM_G_FLOAT(OFS_RETURN) = -1;
1773 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1780 fclose(float fhandle)
1783 //void(float fhandle) fclose = #111; // closes a file
1784 void VM_fclose(void)
1788 VM_SAFEPARMCOUNT(1,VM_fclose);
1790 filenum = PRVM_G_FLOAT(OFS_PARM0);
1791 if (filenum < 0 || filenum >= MAX_VMFILES)
1793 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1796 if (VM_FILES[filenum] == NULL)
1798 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1801 FS_Close(VM_FILES[filenum]);
1802 VM_FILES[filenum] = NULL;
1809 string fgets(float fhandle)
1812 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1816 static char string[VM_STRINGTEMP_LENGTH];
1819 VM_SAFEPARMCOUNT(1,VM_fgets);
1821 filenum = PRVM_G_FLOAT(OFS_PARM0);
1822 if (filenum < 0 || filenum >= MAX_VMFILES)
1824 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1827 if (VM_FILES[filenum] == NULL)
1829 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1835 c = FS_Getc(VM_FILES[filenum]);
1836 if (c == '\r' || c == '\n' || c < 0)
1838 if (end < VM_STRINGTEMP_LENGTH - 1)
1842 // remove \n following \r
1844 c = FS_Getc(VM_FILES[filenum]);
1845 if (developer.integer >= 3)
1846 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1848 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1850 PRVM_G_INT(OFS_RETURN) = 0;
1857 fputs(float fhandle, string s)
1860 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1864 char string[VM_STRINGTEMP_LENGTH];
1867 VM_SAFEPARMCOUNT(2,VM_fputs);
1869 filenum = PRVM_G_FLOAT(OFS_PARM0);
1870 if (filenum < 0 || filenum >= MAX_VMFILES)
1872 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1875 if (VM_FILES[filenum] == NULL)
1877 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1880 VM_VarString(1, string, sizeof(string));
1881 if ((stringlength = strlen(string)))
1882 FS_Write(VM_FILES[filenum], string, stringlength);
1883 if (developer.integer)
1884 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1891 float strlen(string s)
1894 //float(string s) strlen = #114; // returns how many characters are in a string
1895 void VM_strlen(void)
1899 VM_SAFEPARMCOUNT(1,VM_strlen);
1901 s = PRVM_G_STRING(OFS_PARM0);
1903 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1905 PRVM_G_FLOAT(OFS_RETURN) = 0;
1912 string strcat(string,string,...[string])
1915 //string(string s1, string s2) strcat = #115;
1916 // concatenates two strings (for example "abc", "def" would return "abcdef")
1917 // and returns as a tempstring
1918 void VM_strcat(void)
1923 PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
1925 s = VM_GetTempString();
1926 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1927 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1934 string substring(string s, float start, float length)
1937 // string(string s, float start, float length) substring = #116;
1938 // returns a section of a string as a tempstring
1939 void VM_substring(void)
1941 int i, start, length;
1944 VM_SAFEPARMCOUNT(3,VM_substring);
1946 string = VM_GetTempString();
1947 s = PRVM_G_STRING(OFS_PARM0);
1948 start = PRVM_G_FLOAT(OFS_PARM1);
1949 length = PRVM_G_FLOAT(OFS_PARM2);
1952 for (i = 0;i < start && *s;i++, s++);
1953 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1956 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1963 vector stov(string s)
1966 //vector(string s) stov = #117; // returns vector value from a string
1969 char string[VM_STRINGTEMP_LENGTH];
1971 VM_SAFEPARMCOUNT(1,VM_stov);
1973 VM_VarString(0, string, sizeof(string));
1974 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1981 string strzone(string s)
1984 //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)
1985 void VM_strzone(void)
1989 VM_SAFEPARMCOUNT(1,VM_strzone);
1991 in = PRVM_G_STRING(OFS_PARM0);
1992 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1994 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
2004 //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!!!)
2005 void VM_strunzone(void)
2008 VM_SAFEPARMCOUNT(1,VM_strunzone);
2010 str = PRVM_G_STRING(OFS_PARM0);
2011 if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
2012 PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
2019 VM_command (used by client and menu)
2021 clientcommand(float client, string s) (for client and menu)
2024 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2025 //this function originally written by KrimZon, made shorter by LordHavoc
2026 void VM_clcommand (void)
2028 client_t *temp_client;
2031 VM_SAFEPARMCOUNT(2,VM_clcommand);
2033 i = PRVM_G_FLOAT(OFS_PARM0);
2034 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2036 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
2040 temp_client = host_client;
2041 host_client = svs.clients + i;
2042 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2043 host_client = temp_client;
2051 float tokenize(string s)
2054 //float(string s) tokenize = #441;
2055 // takes apart a string into individal words (access them with argv), returns how many
2056 // this function originally written by KrimZon, made shorter by LordHavoc
2057 static char **tokens = NULL;
2058 static int max_tokens, num_tokens = 0;
2059 void VM_tokenize (void)
2064 VM_SAFEPARMCOUNT(1,VM_tokenize);
2066 str = PRVM_G_STRING(OFS_PARM0);
2071 for (i=0;i<num_tokens;i++)
2077 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2078 max_tokens = strlen(str);
2080 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2082 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2083 strcpy(tokens[num_tokens], com_token);
2086 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2093 string argv(float n)
2096 //string(float n) argv = #442;
2097 // returns a word from the tokenized string (returns nothing for an invalid index)
2098 // this function originally written by KrimZon, made shorter by LordHavoc
2103 VM_SAFEPARMCOUNT(1,VM_argv);
2105 token_num = PRVM_G_FLOAT(OFS_PARM0);
2106 if (token_num >= 0 && token_num < num_tokens)
2107 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2109 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2113 //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)
2114 void PF_setattachment (void)
2116 edict_t *e = G_EDICT(OFS_PARM0);
2117 edict_t *tagentity = G_EDICT(OFS_PARM1);
2118 char *tagname = G_STRING(OFS_PARM2);
2123 if (tagentity == NULL)
2124 tagentity = sv.edicts;
2126 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2128 v->edict = EDICT_TO_PROG(tagentity);
2130 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2133 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2135 modelindex = (int)tagentity->v->modelindex;
2136 if (modelindex >= 0 && modelindex < MAX_MODELS)
2138 model = sv.models[modelindex];
2139 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2140 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2141 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2143 // FIXME: use a model function to get tag info (need to handle skeletal)
2144 if (v->_float == 0 && model->alias.aliasnum_tags)
2145 for (i = 0;i < model->alias.aliasnum_tags;i++)
2146 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2149 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);
2152 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));
2163 void VM_isserver(void)
2165 VM_SAFEPARMCOUNT(0,VM_serverstate);
2167 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2177 void VM_clientcount(void)
2179 VM_SAFEPARMCOUNT(0,VM_clientcount);
2181 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2191 void VM_clientstate(void)
2193 VM_SAFEPARMCOUNT(0,VM_clientstate);
2195 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2202 float getostype(void)
2204 */ // not used at the moment -> not included in the common list
2205 void VM_getostype(void)
2207 VM_SAFEPARMCOUNT(0,VM_getostype);
2212 OS_MAC - not supported
2216 PRVM_G_FLOAT(OFS_RETURN) = 0;
2218 PRVM_G_FLOAT(OFS_RETURN) = 2;
2220 PRVM_G_FLOAT(OFS_RETURN) = 1;
2228 vector getmousepos()
2231 void VM_getmousepos(void)
2234 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2236 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2237 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2238 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2248 void VM_gettime(void)
2250 VM_SAFEPARMCOUNT(0,VM_gettime);
2252 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2259 loadfromdata(string data)
2262 void VM_loadfromdata(void)
2264 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2266 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2270 ========================
2271 VM_M_parseentitydata
2273 parseentitydata(entity ent, string data)
2274 ========================
2276 void VM_M_parseentitydata(void)
2281 VM_SAFEPARMCOUNT(2, VM_parseentitydata);
2283 // get edict and test it
2284 ent = PRVM_G_EDICT(OFS_PARM0);
2286 PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
2288 data = PRVM_G_STRING(OFS_PARM1);
2290 // parse the opening brace
2291 if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
2292 PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
2294 PRVM_ED_ParseEdict (data, ent);
2301 loadfromfile(string file)
2304 void VM_loadfromfile(void)
2309 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2311 filename = PRVM_G_STRING(OFS_PARM0);
2312 // .. is parent directory on many platforms
2313 // / is parent directory on Amiga
2314 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2315 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2316 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2318 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2319 PRVM_G_FLOAT(OFS_RETURN) = -4;
2323 // not conform with VM_fopen
2324 data = FS_LoadFile(filename, tempmempool, false);
2326 PRVM_G_FLOAT(OFS_RETURN) = -1;
2328 PRVM_ED_LoadFromFile(data);
2339 float mod(float val, float m)
2342 void VM_modulo(void)
2345 VM_SAFEPARMCOUNT(2,VM_module);
2347 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2348 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2350 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2353 void VM_Search_Init(void)
2355 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2358 void VM_Search_Reset(void)
2361 // reset the fssearch list
2362 for(i = 0; i < MAX_VMSEARCHES; i++)
2363 if(VM_SEARCHLIST[i])
2364 FS_FreeSearch(VM_SEARCHLIST[i]);
2365 memset(VM_SEARCHLIST,0,sizeof(fssearch_t*[MAX_VMSEARCHES]));
2372 float search_begin(string pattern, float caseinsensitive, float quiet)
2375 void VM_search_begin(void)
2379 int caseinsens, quiet;
2381 VM_SAFEPARMCOUNT(3, VM_search_begin);
2383 pattern = PRVM_G_STRING(OFS_PARM0);
2385 VM_CheckEmptyString(pattern);
2387 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
2388 quiet = PRVM_G_FLOAT(OFS_PARM2);
2390 for(handle = 0; handle < MAX_VMSEARCHES; handle++)
2391 if(!VM_SEARCHLIST[handle])
2394 if(handle >= MAX_VMSEARCHES)
2396 Con_Printf("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, MAX_VMSEARCHES);
2397 PRVM_G_FLOAT(OFS_RETURN) = -2;
2401 if(!(VM_SEARCHLIST[handle] = FS_Search(pattern,caseinsens, quiet)))
2402 PRVM_G_FLOAT(OFS_RETURN) = -1;
2404 PRVM_G_FLOAT(OFS_RETURN) = handle;
2411 void search_end(float handle)
2414 void VM_search_end(void)
2417 VM_SAFEPARMCOUNT(1, VM_search_end);
2419 handle = PRVM_G_FLOAT(OFS_PARM0);
2421 if(handle < 0 || handle >= MAX_VMSEARCHES)
2423 Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
2426 if(VM_SEARCHLIST[handle] == NULL)
2428 Con_Printf("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
2432 FS_FreeSearch(VM_SEARCHLIST[handle]);
2433 VM_SEARCHLIST[handle] = NULL;
2440 float search_getsize(float handle)
2443 void VM_search_getsize(void)
2446 VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
2448 handle = PRVM_G_FLOAT(OFS_PARM0);
2450 if(handle < 0 || handle >= MAX_VMSEARCHES)
2452 Con_Printf("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
2455 if(VM_SEARCHLIST[handle] == NULL)
2457 Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
2461 PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
2466 VM_search_getfilename
2468 string search_getfilename(float handle, float num)
2471 void VM_search_getfilename(void)
2473 int handle, filenum;
2475 VM_SAFEPARMCOUNT(2, VM_search_getfilename);
2477 handle = PRVM_G_FLOAT(OFS_PARM0);
2478 filenum = PRVM_G_FLOAT(OFS_PARM1);
2480 if(handle < 0 || handle >= MAX_VMSEARCHES)
2482 Con_Printf("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
2485 if(VM_SEARCHLIST[handle] == NULL)
2487 Con_Printf("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
2490 if(filenum < 0 || filenum >= VM_SEARCHLIST[handle]->numfilenames)
2492 Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
2496 tmp = VM_GetTempString();
2497 strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
2499 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2506 string chr(float ascii)
2512 VM_SAFEPARMCOUNT(1, VM_chr);
2514 tmp = VM_GetTempString();
2515 tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
2518 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
2521 //=============================================================================
2522 // Draw builtins (client & menu)
2528 float iscachedpic(string pic)
2531 void VM_iscachedpic(void)
2533 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2535 // drawq hasnt such a function, thus always return true
2536 PRVM_G_FLOAT(OFS_RETURN) = false;
2543 string precache_pic(string pic)
2546 void VM_precache_pic(void)
2550 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2552 s = PRVM_G_STRING(OFS_PARM0);
2553 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2556 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2558 VM_CheckEmptyString (s);
2560 if(!Draw_CachePic(s))
2561 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2571 void VM_freepic(void)
2575 VM_SAFEPARMCOUNT(1,VM_freepic);
2577 s = PRVM_G_STRING(OFS_PARM0);
2580 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2582 VM_CheckEmptyString (s);
2591 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2594 void VM_drawcharacter(void)
2596 float *pos,*scale,*rgb;
2599 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2601 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2604 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2605 PRVM_G_FLOAT(OFS_RETURN) = -1;
2609 pos = PRVM_G_VECTOR(OFS_PARM0);
2610 scale = PRVM_G_VECTOR(OFS_PARM2);
2611 rgb = PRVM_G_VECTOR(OFS_PARM3);
2612 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2614 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2616 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2617 PRVM_G_FLOAT(OFS_RETURN) = -2;
2621 if(pos[2] || scale[2])
2622 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")));
2624 if(!scale[0] || !scale[1])
2626 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2627 PRVM_G_FLOAT(OFS_RETURN) = -3;
2631 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2632 PRVM_G_FLOAT(OFS_RETURN) = 1;
2639 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2642 void VM_drawstring(void)
2644 float *pos,*scale,*rgb;
2647 VM_SAFEPARMCOUNT(6,VM_drawstring);
2649 string = PRVM_G_STRING(OFS_PARM1);
2652 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2653 PRVM_G_FLOAT(OFS_RETURN) = -1;
2657 //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to the precolored letters, too?
2659 pos = PRVM_G_VECTOR(OFS_PARM0);
2660 scale = PRVM_G_VECTOR(OFS_PARM2);
2661 rgb = PRVM_G_VECTOR(OFS_PARM3);
2662 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2664 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2666 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2667 PRVM_G_FLOAT(OFS_RETURN) = -2;
2671 if(!scale[0] || !scale[1])
2673 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2674 PRVM_G_FLOAT(OFS_RETURN) = -3;
2678 if(pos[2] || scale[2])
2679 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")));
2681 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2682 PRVM_G_FLOAT(OFS_RETURN) = 1;
2688 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2691 void VM_drawpic(void)
2694 float *size, *pos, *rgb;
2697 VM_SAFEPARMCOUNT(6,VM_drawpic);
2699 pic = PRVM_G_STRING(OFS_PARM1);
2703 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2704 PRVM_G_FLOAT(OFS_RETURN) = -1;
2708 VM_CheckEmptyString (pic);
2710 // is pic cached ? no function yet for that
2713 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2714 PRVM_G_FLOAT(OFS_RETURN) = -4;
2718 pos = PRVM_G_VECTOR(OFS_PARM0);
2719 size = PRVM_G_VECTOR(OFS_PARM2);
2720 rgb = PRVM_G_VECTOR(OFS_PARM3);
2721 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2723 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2725 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2726 PRVM_G_FLOAT(OFS_RETURN) = -2;
2730 if(pos[2] || size[2])
2731 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")));
2733 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2734 PRVM_G_FLOAT(OFS_RETURN) = 1;
2741 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2744 void VM_drawfill(void)
2746 float *size, *pos, *rgb;
2749 VM_SAFEPARMCOUNT(5,VM_drawfill);
2752 pos = PRVM_G_VECTOR(OFS_PARM0);
2753 size = PRVM_G_VECTOR(OFS_PARM1);
2754 rgb = PRVM_G_VECTOR(OFS_PARM2);
2755 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2757 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2759 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2760 PRVM_G_FLOAT(OFS_RETURN) = -2;
2764 if(pos[2] || size[2])
2765 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")));
2767 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2768 PRVM_G_FLOAT(OFS_RETURN) = 1;
2775 drawsetcliparea(float x, float y, float width, float height)
2778 void VM_drawsetcliparea(void)
2781 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2783 x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
2784 y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
2785 w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth - x));
2786 h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
2788 DrawQ_SetClipArea(x, y, w, h);
2793 VM_drawresetcliparea
2798 void VM_drawresetcliparea(void)
2800 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2802 DrawQ_ResetClipArea();
2809 vector getimagesize(string pic)
2812 void VM_getimagesize(void)
2817 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2819 p = PRVM_G_STRING(OFS_PARM0);
2822 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2824 VM_CheckEmptyString (p);
2826 pic = Draw_CachePic (p);
2828 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2829 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2830 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2833 // CL_Video interface functions
2836 ========================
2839 float cin_open(string file, string name)
2840 ========================
2842 void VM_cin_open( void )
2847 VM_SAFEPARMCOUNT( 2, VM_cin_open );
2849 file = PRVM_G_STRING( OFS_PARM0 );
2850 name = PRVM_G_STRING( OFS_PARM1 );
2852 VM_CheckEmptyString( file );
2853 VM_CheckEmptyString( name );
2855 if( CL_OpenVideo( file, name, MENUOWNER ) )
2856 PRVM_G_FLOAT( OFS_RETURN ) = 1;
2858 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2862 ========================
2865 void cin_close(string name)
2866 ========================
2868 void VM_cin_close( void )
2872 VM_SAFEPARMCOUNT( 1, VM_cin_close );
2874 name = PRVM_G_STRING( OFS_PARM0 );
2875 VM_CheckEmptyString( name );
2877 CL_CloseVideo( CL_GetVideo( name ) );
2881 ========================
2883 void cin_setstate(string name, float type)
2884 ========================
2886 void VM_cin_setstate( void )
2889 clvideostate_t state;
2892 VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
2894 name = PRVM_G_STRING( OFS_PARM0 );
2895 VM_CheckEmptyString( name );
2897 state = PRVM_G_FLOAT( OFS_PARM1 );
2899 video = CL_GetVideo( name );
2900 if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
2901 CL_SetVideoState( video, state );
2905 ========================
2908 float cin_getstate(string name)
2909 ========================
2911 void VM_cin_getstate( void )
2916 VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
2918 name = PRVM_G_STRING( OFS_PARM0 );
2919 VM_CheckEmptyString( name );
2921 video = CL_GetVideo( name );
2923 PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
2925 PRVM_G_FLOAT( OFS_RETURN ) = 0;
2929 ========================
2932 void cin_restart(string name)
2933 ========================
2935 void VM_cin_restart( void )
2940 VM_SAFEPARMCOUNT( 1, VM_cin_restart );
2942 name = PRVM_G_STRING( OFS_PARM0 );
2943 VM_CheckEmptyString( name );
2945 video = CL_GetVideo( name );
2947 CL_RestartVideo( video );
2950 ////////////////////////////////////////
2951 // AltString functions
2952 ////////////////////////////////////////
2955 ========================
2958 float altstr_count(string)
2959 ========================
2961 void VM_altstr_count( void )
2966 VM_SAFEPARMCOUNT( 1, VM_altstr_count );
2968 altstr = PRVM_G_STRING( OFS_PARM0 );
2969 VM_CheckEmptyString( altstr );
2971 for( count = 0, pos = altstr ; *pos ; pos++ )
2972 if( *pos == '\\' && !*++pos )
2974 else if( *pos == '\'' )
2977 PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
2981 ========================
2984 string altstr_prepare(string)
2985 ========================
2987 void VM_altstr_prepare( void )
2993 VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
2995 instr = PRVM_G_STRING( OFS_PARM0 );
2996 VM_CheckEmptyString( instr );
2997 outstr = VM_GetTempString();
2999 for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
3008 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3012 ========================
3015 string altstr_get(string, float)
3016 ========================
3018 void VM_altstr_get( void )
3020 char *altstr, *pos, *outstr, *out;
3023 VM_SAFEPARMCOUNT( 2, VM_altstr_get );
3025 altstr = PRVM_G_STRING( OFS_PARM0 );
3026 VM_CheckEmptyString( altstr );
3028 count = PRVM_G_FLOAT( OFS_PARM1 );
3029 count = count * 2 + 1;
3031 for( pos = altstr ; *pos && count ; pos++ )
3032 if( *pos == '\\' && !*++pos )
3034 else if( *pos == '\'' )
3038 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3042 outstr = VM_GetTempString();
3043 for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
3044 if( *pos == '\\' ) {
3049 } else if( *pos == '\'' )
3055 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3059 ========================
3062 string altstr_set(string altstr, float num, string set)
3063 ========================
3065 void VM_altstr_set( void )
3072 VM_SAFEPARMCOUNT( 3, VM_altstr_set );
3074 altstr = PRVM_G_STRING( OFS_PARM0 );
3075 VM_CheckEmptyString( altstr );
3077 num = PRVM_G_FLOAT( OFS_PARM1 );
3079 str = PRVM_G_STRING( OFS_PARM2 );
3080 VM_CheckEmptyString( str );
3082 outstr = out = VM_GetTempString();
3083 for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
3084 if( *in == '\\' && !*++in )
3086 else if( *in == '\'' )
3090 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3094 for( ; *str; *out++ = *str++ );
3095 // now jump over the old contents
3096 for( ; *in; *out++ = *in++ )
3097 if( *in == '\'' || *in == '\\' && !*++in )
3101 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
3106 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
3109 void VM_Cmd_Init(void)
3111 // only init the stuff for the current prog
3112 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
3117 void VM_Cmd_Reset(void)
3119 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
3120 if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
3121 memheader_t *header;
3124 for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
3125 Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
3128 Mem_FreePool(&VM_STRINGS_MEMPOOL);
3129 CL_PurgeOwner( MENUOWNER );
3131 VM_Files_CloseAll();
3134 //============================================================================
3137 char *vm_sv_extensions =
3140 prvm_builtin_t vm_sv_builtins[] = {
3141 0 // to be consistent with the old vm
3144 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3146 void VM_SV_Cmd_Init(void)
3150 void VM_SV_Cmd_Reset(void)
3154 //============================================================================
3157 char *vm_cl_extensions =
3160 prvm_builtin_t vm_cl_builtins[] = {
3161 0 // to be consistent with the old vm
3164 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3166 void VM_CL_Cmd_Init(void)
3170 void VM_CL_Cmd_Reset(void)
3174 //============================================================================
3177 char *vm_m_extensions =
3184 setmousetarget(float target)
3187 void VM_M_setmousetarget(void)
3189 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
3191 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3194 in_client_mouse = false;
3197 in_client_mouse = true;
3200 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
3208 float getmousetarget
3211 void VM_M_getmousetarget(void)
3213 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
3216 PRVM_G_FLOAT(OFS_RETURN) = 2;
3218 PRVM_G_FLOAT(OFS_RETURN) = 1;
3227 setkeydest(float dest)
3230 void VM_M_setkeydest(void)
3232 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
3234 switch((int)PRVM_G_FLOAT(OFS_PARM0))
3238 key_dest = key_game;
3242 key_dest = key_menu;
3246 // key_dest = key_message
3249 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
3260 void VM_M_getkeydest(void)
3262 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
3264 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
3268 PRVM_G_FLOAT(OFS_RETURN) = 0;
3271 PRVM_G_FLOAT(OFS_RETURN) = 2;
3275 // PRVM_G_FLOAT(OFS_RETURN) = 1;
3278 PRVM_G_FLOAT(OFS_RETURN) = 3;
3286 callfunction(...,string function_name)
3290 mfunction_t *PRVM_ED_FindFunction (const char *name);
3291 void VM_M_callfunction(void)
3297 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
3299 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
3302 PRVM_ERROR("VM_M_callfunction: null string !\n");
3304 VM_CheckEmptyString(s);
3306 func = PRVM_ED_FindFunction(s);
3309 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
3310 else if (func->first_statement < 0)
3312 // negative statements are built in functions
3313 int builtinnumber = -func->first_statement;
3314 prog->xfunction->builtinsprofile++;
3315 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
3316 prog->builtins[builtinnumber]();
3318 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
3323 PRVM_ExecuteProgram(func - prog->functions,"");
3332 float isfunction(string function_name)
3335 mfunction_t *PRVM_ED_FindFunction (const char *name);
3336 void VM_M_isfunction(void)
3341 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
3343 s = PRVM_G_STRING(OFS_PARM0);
3346 PRVM_ERROR("VM_M_isfunction: null string !\n");
3348 VM_CheckEmptyString(s);
3350 func = PRVM_ED_FindFunction(s);
3353 PRVM_G_FLOAT(OFS_RETURN) = false;
3355 PRVM_G_FLOAT(OFS_RETURN) = true;
3362 writetofile(float fhandle, entity ent)
3365 void VM_M_writetofile(void)
3370 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
3372 filenum = PRVM_G_FLOAT(OFS_PARM0);
3373 if (filenum < 0 || filenum >= MAX_VMFILES)
3375 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
3378 if (VM_FILES[filenum] == NULL)
3380 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
3384 ent = PRVM_G_EDICT(OFS_PARM1);
3387 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
3391 PRVM_ED_Write (VM_FILES[filenum], ent);
3398 vector getresolution(float number)
3401 extern unsigned short video_resolutions[][2];
3402 void VM_M_getresolution(void)
3405 VM_SAFEPARMCOUNT(1, VM_getresolution);
3407 nr = PRVM_G_FLOAT(OFS_PARM0);
3410 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
3411 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
3412 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
3419 string keynumtostring(float keynum)
3422 void VM_M_keynumtostring(void)
3426 VM_SAFEPARMCOUNT(1, VM_M_keynumtostring);
3428 keynum = PRVM_G_FLOAT(OFS_PARM0);
3430 tmp = VM_GetTempString();
3432 strcpy(tmp, Key_KeynumToString(keynum));
3434 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
3439 VM_M_findkeysforcommand
3441 string findkeysforcommand(string command)
3443 the returned string is an altstring
3446 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
3448 void M_FindKeysForCommand(char *command, int *keys);
3449 void VM_M_findkeysforcommand(void)
3455 VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
3457 cmd = PRVM_G_STRING(OFS_PARM0);
3459 VM_CheckEmptyString(cmd);
3461 (ret = VM_GetTempString())[0] = 0;
3463 M_FindKeysForCommand(cmd, keys);
3465 for(i = 0; i < NUMKEYS; i++)
3466 ret = strcat(ret, va(" \'%i\'", keys[i]));
3468 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
3473 VM_M_gethostcachestat
3475 float gethostcachestat(float type)
3480 0 hostcache_viewcount
3481 1 hostcache_totalcount
3487 void VM_M_gethostcachestat( void )
3490 VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachestat );
3492 PRVM_G_FLOAT( OFS_RETURN ) = 0;
3494 type = PRVM_G_FLOAT( OFS_PARM0 );
3495 if( type < 0 || type > 4 )
3496 Con_Printf( "VM_M_gethostcachestat: bad type %i!\n", type );
3500 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_viewcount;
3503 PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_cachecount;
3505 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
3508 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
3511 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
3514 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
3520 ========================
3521 VM_M_sethostcachemask
3523 sethostcachemask( string map, string mod, string name,
3524 ========================
3530 VM_M_gethostcachestring
3532 string gethostcachestring(float type, float hostnr)
3540 void VM_M_gethostcachestring(void)
3545 VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
3547 PRVM_G_INT(OFS_RETURN) = 0;
3549 type = PRVM_G_FLOAT(OFS_PARM0);
3551 if(type < 0 || type > 2)
3553 Con_Print("VM_M_gethostcachestring: bad string type requested!\n");
3557 hostnr = PRVM_G_FLOAT(OFS_PARM1);
3559 if(hostnr < 0 || hostnr >= hostcache_viewcount)
3561 Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
3566 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache_viewset[hostnr]->info.cname );
3567 else if( type == 1 )
3568 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache_viewset[hostnr]->line1 );
3570 PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache_viewset[hostnr]->line2 );
3573 prvm_builtin_t vm_m_builtins[] = {
3574 0, // to be consistent with the old vm
3575 // common builtings (mostly)
3652 VM_search_getfilename, // 77
3656 VM_itof, // isString
3660 VM_altstr_set, // 85
3674 VM_WriteEntity, // 408
3690 VM_drawresetcliparea,
3691 VM_getimagesize,// 460
3696 VM_cin_restart, // 465
3705 VM_M_setmousetarget,
3706 VM_M_getmousetarget,
3711 VM_M_keynumtostring,
3712 VM_M_findkeysforcommand,// 610
3713 VM_M_gethostcachestat,
3714 VM_M_gethostcachestring,
3715 VM_M_parseentitydata // 613
3718 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3720 void VM_M_Cmd_Init(void)
3725 void VM_M_Cmd_Reset(void)