2 // Basically every vm builtin cmd should be in here.
3 // All 3 builtin list and extension lists can be found here
4 // cause large (I think they will) are from pr_cmds the same copyright like in pr_cms
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)
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)
92 perhaps only : Menu : WriteMsg
93 ===============================
95 WriteByte(float data, float dest, float desto)
96 WriteChar(float data, float dest, float desto)
97 WriteShort(float data, float dest, float desto)
98 WriteLong(float data, float dest, float desto)
99 WriteAngle(float data, float dest, float desto)
100 WriteCoord(float data, float dest, float desto)
101 WriteString(string data, float dest, float desto)
102 WriteEntity(entity data, float dest, float desto)
104 Client & Menu : draw functions
105 ===============================
107 float iscachedpic(string pic)
108 string precache_pic(string pic)
110 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
111 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
112 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
113 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
114 drawsetcliparea(float x, float y, float width, float height)
116 vector getimagesize(string pic)
119 ==============================================================================
123 setkeydest(float dest)
125 setmousetarget(float target)
126 float getmousetarget(void)
128 callfunction(...,string function_name)
129 writetofile(float fhandle, entity ent)
132 #include "quakedef.h"
133 #include "progdefs.h"
134 #include "clprogdefs.h"
135 #include "mprogdefs.h"
137 //============================================================================
138 // nice helper macros
140 #ifndef VM_NOPARMCHECK
141 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
143 #define VM_SAFEPARMCOUNT(p,f)
146 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
148 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
150 #define e10 0,0,0,0,0,0,0,0,0,0
151 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
152 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
154 //============================================================================
157 // string zone mempool
158 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
160 // temp string handling
161 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
162 #define VM_STRINGTEMP_BUFFERS 16
163 #define VM_STRINGTEMP_LENGTH 4096
164 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
165 static int vm_string_tempindex = 0;
168 #define MAX_QC_CVARS 128 * PRVM_MAXPROGS
169 cvar_t vm_qc_cvar[MAX_QC_CVARS];
170 int vm_currentqc_cvar;
173 #define MAX_VMFILES 256
174 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
175 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
177 qfile_t *vm_files[MAX_PRVMFILES];
179 static char *VM_GetTempString(void)
182 s = vm_string_temp[vm_string_tempindex];
183 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
187 void VM_CheckEmptyString (char *s)
190 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
193 //============================================================================
196 void VM_VarString(int first, char *out, int outlength)
202 outend = out + outlength - 1;
203 for (i = first;i < prog->argc && out < outend;i++)
205 s = PRVM_G_STRING((OFS_PARM0+i*3));
206 while (out < outend && *s)
216 returns true if the extension is supported by the server
218 checkextension(extensionname)
222 // kind of helper function
223 static qboolean checkextension(char *name)
229 for (e = prog->extensionstring;*e;e++)
236 while (*e && *e != ' ')
238 if (e - start == len)
239 if (!strncasecmp(start, name, len))
247 void VM_checkextension (void)
249 VM_SAFEPARMCOUNT(1,VM_checkextension);
251 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
258 This is a TERMINAL error, which will kill off the entire prog.
267 char string[VM_STRINGTEMP_LENGTH];
269 VM_VarString(0, string, sizeof(string));
270 Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
273 ed = PRVM_G_EDICT(prog->self->ofs);
277 PRVM_ERROR ("%s: Program error", PRVM_NAME);
284 Dumps out self, then an error message. The program is aborted and self is
285 removed, but the level can continue.
290 void VM_objerror (void)
293 char string[VM_STRINGTEMP_LENGTH];
295 VM_VarString(0, string, sizeof(string));
296 Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
299 ed = PRVM_G_EDICT (prog->self->ofs);
305 // objerror has to display the object fields -> else call
306 PRVM_ERROR ("VM_objecterror: self not defined !\n");
311 VM_print (actually used only by client and menu)
320 char string[VM_STRINGTEMP_LENGTH];
322 VM_VarString(0, string, sizeof(string));
330 broadcast print to everyone on server
335 void VM_bprint (void)
337 char string[VM_STRINGTEMP_LENGTH];
341 Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
345 VM_VarString(0, string, sizeof(string));
346 SV_BroadcastPrintf("%s", string);
351 VM_sprint (menu & client but only if server.active == true)
353 single print to a specific client
355 sprint(float clientnum,...[string])
358 void VM_sprint (void)
362 char string[VM_STRINGTEMP_LENGTH];
364 //find client for this entity
365 clientnum = PRVM_G_FLOAT(OFS_PARM0);
366 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
368 Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
372 client = svs.clients + clientnum;
373 if (!client->netconnection)
375 VM_VarString(1, string, sizeof(string));
376 MSG_WriteChar(&client->message,svc_print);
377 MSG_WriteString(&client->message, string);
384 single print to the screen
386 centerprint(clientent, value)
389 void VM_centerprint (void)
391 char string[VM_STRINGTEMP_LENGTH];
393 VM_VarString(0, string, sizeof(string));
394 SCR_CenterPrint(string);
401 vector normalize(vector)
404 void VM_normalize (void)
410 VM_SAFEPARMCOUNT(1,VM_normalize);
412 value1 = PRVM_G_VECTOR(OFS_PARM0);
414 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
418 newvalue[0] = newvalue[1] = newvalue[2] = 0;
422 newvalue[0] = value1[0] * new;
423 newvalue[1] = value1[1] * new;
424 newvalue[2] = value1[2] * new;
427 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
442 VM_SAFEPARMCOUNT(1,VM_vlen);
444 value1 = PRVM_G_VECTOR(OFS_PARM0);
446 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
449 PRVM_G_FLOAT(OFS_RETURN) = new;
456 float vectoyaw(vector)
459 void VM_vectoyaw (void)
464 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
466 value1 = PRVM_G_VECTOR(OFS_PARM0);
468 if (value1[1] == 0 && value1[0] == 0)
472 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
477 PRVM_G_FLOAT(OFS_RETURN) = yaw;
485 vector vectoangles(vector)
488 void VM_vectoangles (void)
494 VM_SAFEPARMCOUNT(1,VM_vectoangles);
496 value1 = PRVM_G_VECTOR(OFS_PARM0);
498 if (value1[1] == 0 && value1[0] == 0)
508 // LordHavoc: optimized a bit
511 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
515 else if (value1[1] > 0)
520 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
521 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
526 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
527 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
528 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
535 Returns a number from 0<= num < 1
540 void VM_random (void)
544 VM_SAFEPARMCOUNT(0,VM_random);
546 num = (rand ()&0x7fff) / ((float)0x7fff);
548 PRVM_G_FLOAT(OFS_RETURN) = num;
555 Each entity can have eight independant sound sources, like voice,
558 Channel 0 is an auto-allocate channel, the others override anything
559 already running on that entity/channel pair.
561 An attenuation of 0 will play full volume everywhere in the level.
562 Larger attenuations will drop off.
575 entity = G_EDICT(OFS_PARM0);
576 channel = G_FLOAT(OFS_PARM1);
577 sample = G_STRING(OFS_PARM2);
578 volume = G_FLOAT(OFS_PARM3) * 255;
579 attenuation = G_FLOAT(OFS_PARM4);
581 if (volume < 0 || volume > 255)
582 Host_Error ("SV_StartSound: volume = %i", volume);
584 if (attenuation < 0 || attenuation > 4)
585 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
587 if (channel < 0 || channel > 7)
588 Host_Error ("SV_StartSound: channel = %i", channel);
590 SV_StartSound (entity, channel, sample, volume, attenuation);
598 localsound(string sample)
601 void VM_localsound(void)
605 VM_SAFEPARMCOUNT(1,VM_localsound);
607 s = PRVM_G_STRING(OFS_PARM0);
611 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
612 PRVM_G_FLOAT(OFS_RETURN) = -4;
617 PRVM_G_FLOAT(OFS_RETURN) = 1;
629 PRVM_ERROR ("%s: break statement", PRVM_NAME);
632 //============================================================================
638 Sends text over to the client's execution buffer
640 [localcmd (string) or]
644 void VM_localcmd (void)
646 VM_SAFEPARMCOUNT(1,VM_localcmd);
648 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
660 VM_SAFEPARMCOUNT(1,VM_cvar);
662 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
669 const string str_cvar (string)
672 void VM_str_cvar(void)
675 const char *cvar_string;
676 VM_SAFEPARMCOUNT(1,VM_str_cvar);
678 name = PRVM_G_STRING(OFS_PARM0);
681 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
683 VM_CheckEmptyString(name);
685 out = VM_GetTempString();
687 cvar_string = Cvar_VariableString(name);
689 strcpy(out, cvar_string);
691 PRVM_G_INT(OFS_PARM0) = PRVM_SetString(out);
698 void cvar_set (string,string)
701 void VM_cvar_set (void)
703 VM_SAFEPARMCOUNT(2,VM_cvar_set);
705 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
715 void VM_dprint (void)
717 char string[VM_STRINGTEMP_LENGTH];
718 if (developer.integer)
720 VM_VarString(0, string, sizeof(string));
721 Con_Printf("%s: %s", PRVM_NAME, string);
738 VM_SAFEPARMCOUNT(1, VM_ftos);
740 v = PRVM_G_FLOAT(OFS_PARM0);
742 s = VM_GetTempString();
743 if ((float)((int)v) == v)
744 sprintf(s, "%i", (int)v);
747 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
762 VM_SAFEPARMCOUNT(1,VM_fabs);
764 v = PRVM_G_FLOAT(OFS_PARM0);
765 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
780 VM_SAFEPARMCOUNT(1,VM_vtos);
782 s = VM_GetTempString();
783 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]);
784 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
799 VM_SAFEPARMCOUNT(1, VM_etos);
801 s = VM_GetTempString();
802 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
803 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
810 float stof(...[string])
815 char string[VM_STRINGTEMP_LENGTH];
816 VM_VarString(0, string, sizeof(string));
817 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
831 prog->xfunction->builtinsprofile += 20;
832 ed = PRVM_ED_Alloc();
844 void VM_remove (void)
847 prog->xfunction->builtinsprofile += 20;
849 VM_SAFEPARMCOUNT(1, VM_remove);
851 ed = PRVM_G_EDICT(OFS_PARM0);
852 // if (ed == prog->edicts)
853 // PRVM_ERROR ("remove: tried to remove world\n");
854 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
855 // Host_Error("remove: tried to remove a client\n");
863 entity find(entity start, .string field, string match)
874 VM_SAFEPARMCOUNT(3,VM_find);
876 e = PRVM_G_EDICTNUM(OFS_PARM0);
877 f = PRVM_G_INT(OFS_PARM1);
878 s = PRVM_G_STRING(OFS_PARM2);
882 // return reserved edict 0 (could be used for whatever the prog wants)
883 VM_RETURN_EDICT(prog->edicts);
887 for (e++ ; e < prog->num_edicts ; e++)
889 prog->xfunction->builtinsprofile++;
890 ed = PRVM_EDICT_NUM(e);
893 t = PRVM_E_STRING(ed,f);
903 VM_RETURN_EDICT(prog->edicts);
910 entity findfloat(entity start, .float field, float match)
911 entity findentity(entity start, .entity field, entity match)
914 // LordHavoc: added this for searching float, int, and entity reference fields
915 void VM_findfloat (void)
922 VM_SAFEPARMCOUNT(3,VM_findfloat);
924 e = PRVM_G_EDICTNUM(OFS_PARM0);
925 f = PRVM_G_INT(OFS_PARM1);
926 s = PRVM_G_FLOAT(OFS_PARM2);
928 for (e++ ; e < prog->num_edicts ; e++)
930 prog->xfunction->builtinsprofile++;
931 ed = PRVM_EDICT_NUM(e);
934 if (PRVM_E_FLOAT(ed,f) == s)
941 VM_RETURN_EDICT(prog->edicts);
948 entity findchain(.string field, string match)
951 int PRVM_ED_FindFieldOffset(const char *field);
952 // chained search for strings in entity fields
953 // entity(.string field, string match) findchain = #402;
954 void VM_findchain (void)
960 prvm_edict_t *ent, *chain;
962 VM_SAFEPARMCOUNT(2,VM_findchain);
964 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
965 if(!prog->flag & PRVM_FE_CHAIN)
966 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
968 chain_of = PRVM_ED_FindFieldOffset ("chain");
970 chain = prog->edicts;
972 f = PRVM_G_INT(OFS_PARM0);
973 s = PRVM_G_STRING(OFS_PARM1);
976 VM_RETURN_EDICT(prog->edicts);
980 ent = PRVM_NEXT_EDICT(prog->edicts);
981 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
983 prog->xfunction->builtinsprofile++;
986 t = PRVM_E_STRING(ent,f);
992 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
996 VM_RETURN_EDICT(chain);
1003 entity findchainfloat(.string field, float match)
1004 entity findchainentity(.string field, entity match)
1007 // LordHavoc: chained search for float, int, and entity reference fields
1008 // entity(.string field, float match) findchainfloat = #403;
1009 void VM_findchainfloat (void)
1015 prvm_edict_t *ent, *chain;
1017 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1019 if(!prog->flag & PRVM_FE_CHAIN)
1020 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1022 chain_of = PRVM_ED_FindFieldOffset ("chain");
1024 chain = (prvm_edict_t *)prog->edicts;
1026 f = PRVM_G_INT(OFS_PARM0);
1027 s = PRVM_G_FLOAT(OFS_PARM1);
1029 ent = PRVM_NEXT_EDICT(prog->edicts);
1030 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1032 prog->xfunction->builtinsprofile++;
1035 if (E_FLOAT(ent,f) != s)
1038 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1042 VM_RETURN_EDICT(chain);
1049 string precache_file(string)
1052 void VM_precache_file (void)
1053 { // precache_file is only used to copy files with qcc, it does nothing
1054 VM_SAFEPARMCOUNT(1,VM_precache_file);
1056 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1063 used instead of the other VM_precache_* functions in the builtin list
1067 void VM_precache_error (void)
1069 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1076 string precache_sound (string sample)
1079 void VM_precache_sound (void)
1083 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1085 s = PRVM_G_STRING(OFS_PARM0);
1086 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1087 VM_CheckEmptyString (s);
1091 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1095 if(!S_PrecacheSound(s,true))
1096 Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1106 void VM_coredump (void)
1108 VM_SAFEPARMCOUNT(0,VM_coredump);
1110 Cbuf_AddText("prvm_edicts ");
1111 Cbuf_AddText(PRVM_NAME);
1125 VM_SAFEPARMCOUNT(0, VM_crash);
1127 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1137 void VM_traceon (void)
1139 VM_SAFEPARMCOUNT(0,VM_traceon);
1151 void VM_traceoff (void)
1153 VM_SAFEPARMCOUNT(0,VM_traceoff);
1155 prog->trace = false;
1165 void VM_eprint (void)
1167 VM_SAFEPARMCOUNT(1,VM_eprint);
1169 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1183 VM_SAFEPARMCOUNT(1,VM_rint);
1185 f = PRVM_G_FLOAT(OFS_PARM0);
1187 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1189 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1199 void VM_floor (void)
1201 VM_SAFEPARMCOUNT(1,VM_floor);
1203 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1215 VM_SAFEPARMCOUNT(1,VM_ceil);
1217 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1225 entity nextent(entity)
1228 void VM_nextent (void)
1233 i = PRVM_G_EDICTNUM(OFS_PARM0);
1236 prog->xfunction->builtinsprofile++;
1238 if (i == prog->num_edicts)
1240 VM_RETURN_EDICT(prog->edicts);
1243 ent = PRVM_EDICT_NUM(i);
1246 VM_RETURN_EDICT(ent);
1253 ===============================================================================
1256 used only for client and menu
1257 severs uses VM_SV_...
1259 Write*(* data, float type, float to)
1261 ===============================================================================
1264 #define MSG_BROADCAST 0 // unreliable to all
1265 #define MSG_ONE 1 // reliable to one (msg_entity)
1266 #define MSG_ALL 2 // reliable to all
1267 #define MSG_INIT 3 // write to the init string
1269 sizebuf_t *VM_WriteDest (void)
1275 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1277 dest = G_FLOAT(OFS_PARM1);
1281 return &sv.datagram;
1284 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1285 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1286 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1288 return &svs.clients[destclient].message;
1291 return &sv.reliable_datagram;
1297 PRVM_ERROR ("WriteDest: bad destination");
1304 void VM_WriteByte (void)
1306 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1309 void VM_WriteChar (void)
1311 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1314 void VM_WriteShort (void)
1316 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1319 void VM_WriteLong (void)
1321 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1324 void VM_WriteAngle (void)
1326 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1329 void VM_WriteCoord (void)
1331 MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1334 void VM_WriteString (void)
1336 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1339 void VM_WriteEntity (void)
1341 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1344 //=============================================================================
1351 changelevel(string map)
1354 void VM_changelevel (void)
1358 VM_SAFEPARMCOUNT(1, VM_changelevel);
1362 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1366 // make sure we don't issue two changelevels
1367 if (svs.changelevel_issued)
1369 svs.changelevel_issued = true;
1371 s = G_STRING(OFS_PARM0);
1372 Cbuf_AddText (va("changelevel %s\n",s));
1384 VM_SAFEPARMCOUNT(1,VM_sin);
1385 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1396 VM_SAFEPARMCOUNT(1,VM_cos);
1397 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1409 VM_SAFEPARMCOUNT(1,VM_sqrt);
1410 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1417 Returns a vector of length < 1 and > 0
1422 void VM_randomvec (void)
1427 VM_SAFEPARMCOUNT(0, VM_randomvec);
1432 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1433 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1434 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1436 while (DotProduct(temp, temp) >= 1);
1437 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1440 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1441 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1442 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1443 // length returned always > 0
1444 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1445 VectorScale(temp,length, temp);*/
1446 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1449 //=============================================================================
1455 float registercvar (string name, string value)
1458 void VM_registercvar (void)
1463 VM_SAFEPARMCOUNT(2,VM_registercvar);
1465 name = PRVM_G_STRING(OFS_PARM0);
1466 value = PRVM_G_STRING(OFS_PARM1);
1467 PRVM_G_FLOAT(OFS_RETURN) = 0;
1468 // first check to see if it has already been defined
1469 if (Cvar_FindVar (name))
1472 // check for overlap with a command
1473 if (Cmd_Exists (name))
1475 Con_Printf ("VM_registercvar: %s is a command\n", name);
1479 if (vm_currentqc_cvar >= MAX_QC_CVARS)
1480 PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1482 // copy the name and value
1483 variable = &vm_qc_cvar[vm_currentqc_cvar++];
1484 variable->name = Z_Malloc (strlen(name)+1);
1485 strcpy (variable->name, name);
1486 variable->string = Z_Malloc (strlen(value)+1);
1487 strcpy (variable->string, value);
1488 variable->value = atof (value);
1490 Cvar_RegisterVariable(variable);
1491 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1498 returns the minimum of two supplied floats
1500 float min(float a, float b, ...[float])
1505 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1506 if (prog->argc == 2)
1507 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1508 else if (prog->argc >= 3)
1511 float f = PRVM_G_FLOAT(OFS_PARM0);
1512 for (i = 1;i < prog->argc;i++)
1513 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1514 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1515 PRVM_G_FLOAT(OFS_RETURN) = f;
1518 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1525 returns the maximum of two supplied floats
1527 float max(float a, float b, ...[float])
1532 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1533 if (prog->argc == 2)
1534 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1535 else if (prog->argc >= 3)
1538 float f = PRVM_G_FLOAT(OFS_PARM0);
1539 for (i = 1;i < prog->argc;i++)
1540 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1541 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1542 G_FLOAT(OFS_RETURN) = f;
1545 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1552 returns number bounded by supplied range
1554 float bound(float min, float value, float max)
1557 void VM_bound (void)
1559 VM_SAFEPARMCOUNT(3,VM_bound);
1560 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1567 returns a raised to power b
1569 float pow(float a, float b)
1574 VM_SAFEPARMCOUNT(2,VM_pow);
1575 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1582 copies data from one entity to another
1584 copyentity(entity src, entity dst)
1587 void VM_copyentity (void)
1589 prvm_edict_t *in, *out;
1590 VM_SAFEPARMCOUNT(2,VM_copyentity);
1591 in = PRVM_G_EDICT(OFS_PARM0);
1592 out = PRVM_G_EDICT(OFS_PARM1);
1593 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1600 sets the color of a client and broadcasts the update to all connected clients
1602 setcolor(clientent, value)
1605 /*void PF_setcolor (void)
1611 entnum = G_EDICTNUM(OFS_PARM0);
1612 i = G_FLOAT(OFS_PARM1);
1614 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1616 Con_Printf ("tried to setcolor a non-client\n");
1620 client = svs.clients + entnum-1;
1621 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1624 client->old_colors = i;
1625 client->edict->v->team = (i & 15) + 1;
1627 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1628 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1629 MSG_WriteByte (&sv.reliable_datagram, i);
1632 void VM_Files_Init(void)
1634 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1637 void VM_Files_CloseAll(void)
1640 for (i = 0;i < MAX_VMFILES;i++)
1643 FS_Close(VM_FILES[i]);
1644 //VM_FILES[i] = NULL;
1646 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1653 float fopen(string filename, float mode)
1656 // float(string filename, float mode) fopen = #110;
1657 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1658 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1662 char *modestring, *filename;
1664 VM_SAFEPARMCOUNT(2,VM_fopen);
1666 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1667 if (VM_FILES[filenum] == NULL)
1669 if (filenum >= MAX_VMFILES)
1671 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1672 PRVM_G_FLOAT(OFS_RETURN) = -2;
1675 mode = PRVM_G_FLOAT(OFS_PARM1);
1678 case 0: // FILE_READ
1681 case 1: // FILE_APPEND
1684 case 2: // FILE_WRITE
1688 Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1689 PRVM_G_FLOAT(OFS_RETURN) = -3;
1692 filename = PRVM_G_STRING(OFS_PARM0);
1693 // .. is parent directory on many platforms
1694 // / is parent directory on Amiga
1695 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1696 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1697 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1699 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1700 PRVM_G_FLOAT(OFS_RETURN) = -4;
1703 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1704 if (VM_FILES[filenum] == NULL)
1705 PRVM_G_FLOAT(OFS_RETURN) = -1;
1707 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1714 fclose(float fhandle)
1717 //void(float fhandle) fclose = #111; // closes a file
1718 void VM_fclose(void)
1722 VM_SAFEPARMCOUNT(1,VM_fclose);
1724 filenum = PRVM_G_FLOAT(OFS_PARM0);
1725 if (filenum < 0 || filenum >= MAX_VMFILES)
1727 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1730 if (VM_FILES[filenum] == NULL)
1732 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1735 FS_Close(VM_FILES[filenum]);
1736 VM_FILES[filenum] = NULL;
1743 string fgets(float fhandle)
1746 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1750 static char string[VM_STRINGTEMP_LENGTH];
1753 VM_SAFEPARMCOUNT(1,VM_fgets);
1755 filenum = PRVM_G_FLOAT(OFS_PARM0);
1756 if (filenum < 0 || filenum >= MAX_VMFILES)
1758 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1761 if (VM_FILES[filenum] == NULL)
1763 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1769 c = FS_Getc(VM_FILES[filenum]);
1770 if (c == '\r' || c == '\n' || c < 0)
1772 if (end < VM_STRINGTEMP_LENGTH - 1)
1776 // remove \n following \r
1778 c = FS_Getc(VM_FILES[filenum]);
1779 if (developer.integer)
1780 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1782 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1784 PRVM_G_INT(OFS_RETURN) = 0;
1791 fputs(float fhandle, string s)
1794 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1798 char string[VM_STRINGTEMP_LENGTH];
1801 VM_SAFEPARMCOUNT(2,VM_fputs);
1803 filenum = PRVM_G_FLOAT(OFS_PARM0);
1804 if (filenum < 0 || filenum >= MAX_VMFILES)
1806 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1809 if (VM_FILES[filenum] == NULL)
1811 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1814 VM_VarString(1, string, sizeof(string));
1815 if ((stringlength = strlen(string)))
1816 FS_Write(VM_FILES[filenum], string, stringlength);
1817 if (developer.integer)
1818 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1825 float strlen(string s)
1828 //float(string s) strlen = #114; // returns how many characters are in a string
1829 void VM_strlen(void)
1833 VM_SAFEPARMCOUNT(1,VM_strlen);
1835 s = PRVM_G_STRING(OFS_PARM0);
1837 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1839 PRVM_G_FLOAT(OFS_RETURN) = 0;
1846 string strcat(string,string,...[string])
1849 //string(string s1, string s2) strcat = #115;
1850 // concatenates two strings (for example "abc", "def" would return "abcdef")
1851 // and returns as a tempstring
1852 void VM_strcat(void)
1857 PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
1859 s = VM_GetTempString();
1860 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1861 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1868 string substring(string s, float start, float length)
1871 // string(string s, float start, float length) substring = #116;
1872 // returns a section of a string as a tempstring
1873 void VM_substring(void)
1875 int i, start, length;
1878 VM_SAFEPARMCOUNT(3,VM_substring);
1880 string = VM_GetTempString();
1881 s = PRVM_G_STRING(OFS_PARM0);
1882 start = PRVM_G_FLOAT(OFS_PARM1);
1883 length = PRVM_G_FLOAT(OFS_PARM2);
1886 for (i = 0;i < start && *s;i++, s++);
1887 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1890 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1897 vector stov(string s)
1900 //vector(string s) stov = #117; // returns vector value from a string
1903 char string[VM_STRINGTEMP_LENGTH];
1905 VM_SAFEPARMCOUNT(1,VM_stov);
1907 VM_VarString(0, string, sizeof(string));
1908 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1915 string strzone(string s)
1918 //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)
1919 void VM_strzone(void)
1923 VM_SAFEPARMCOUNT(1,VM_strzone);
1925 in = PRVM_G_STRING(OFS_PARM0);
1926 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1928 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1938 //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!!!)
1939 void VM_strunzone(void)
1941 VM_SAFEPARMCOUNT(1,VM_strunzone);
1943 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1948 VM_command (used by client and menu)
1950 clientcommand(float client, string s) (for client and menu)
1953 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1954 //this function originally written by KrimZon, made shorter by LordHavoc
1955 void VM_clcommand (void)
1957 client_t *temp_client;
1960 VM_SAFEPARMCOUNT(2,VM_clcommand);
1962 i = PRVM_G_FLOAT(OFS_PARM0);
1963 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1965 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1969 temp_client = host_client;
1970 host_client = svs.clients + i;
1971 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1972 host_client = temp_client;
1980 float tokenize(string s)
1983 //float(string s) tokenize = #441;
1984 // takes apart a string into individal words (access them with argv), returns how many
1985 // this function originally written by KrimZon, made shorter by LordHavoc
1986 static char **tokens = NULL;
1987 static int max_tokens, num_tokens = 0;
1988 void VM_tokenize (void)
1993 VM_SAFEPARMCOUNT(1,VM_tokenize);
1995 str = PRVM_G_STRING(OFS_PARM0);
2000 for (i=0;i<num_tokens;i++)
2006 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2007 max_tokens = strlen(str);
2009 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2011 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2012 strcpy(tokens[num_tokens], com_token);
2015 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2022 string argv(float n)
2025 //string(float n) argv = #442;
2026 // returns a word from the tokenized string (returns nothing for an invalid index)
2027 // this function originally written by KrimZon, made shorter by LordHavoc
2032 VM_SAFEPARMCOUNT(1,VM_argv);
2034 token_num = PRVM_G_FLOAT(OFS_PARM0);
2035 if (token_num >= 0 && token_num < num_tokens)
2036 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2038 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2042 //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)
2043 void PF_setattachment (void)
2045 edict_t *e = G_EDICT(OFS_PARM0);
2046 edict_t *tagentity = G_EDICT(OFS_PARM1);
2047 char *tagname = G_STRING(OFS_PARM2);
2052 if (tagentity == NULL)
2053 tagentity = sv.edicts;
2055 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2057 v->edict = EDICT_TO_PROG(tagentity);
2059 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2062 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2064 modelindex = (int)tagentity->v->modelindex;
2065 if (modelindex >= 0 && modelindex < MAX_MODELS)
2067 model = sv.models[modelindex];
2068 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2069 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2070 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2072 if (v->_float == 0 && model->alias.aliasnum_tags)
2073 for (i = 0;i < model->alias.aliasnum_tags;i++)
2074 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2077 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);
2080 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));
2091 void VM_isserver(void)
2093 VM_SAFEPARMCOUNT(0,VM_serverstate);
2095 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2105 void VM_clientcount(void)
2107 VM_SAFEPARMCOUNT(0,VM_clientcount);
2109 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2119 void VM_clientstate(void)
2121 VM_SAFEPARMCOUNT(0,VM_clientstate);
2123 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2130 float getostype(void)
2132 */ // not used at the moment -> not included in the common list
2133 void VM_getostype(void)
2135 VM_SAFEPARMCOUNT(0,VM_getostype);
2140 OS_MAC - not supported
2144 PRVM_G_FLOAT(OFS_RETURN) = 0;
2146 PRVM_G_FLOAT(OFS_RETURN) = 2;
2148 PRVM_G_FLOAT(OFS_RETURN) = 1;
2156 vector getmousepos()
2159 void VM_getmousepos(void)
2162 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2164 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2165 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2166 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2176 void VM_gettime(void)
2178 VM_SAFEPARMCOUNT(0,VM_gettime);
2180 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2187 loadfromdata(string data)
2190 void VM_loadfromdata(void)
2192 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2194 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2201 loadfromfile(string file)
2204 void VM_loadfromfile(void)
2209 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2211 filename = PRVM_G_STRING(OFS_PARM0);
2212 // .. is parent directory on many platforms
2213 // / is parent directory on Amiga
2214 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2215 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2216 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2218 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2219 PRVM_G_FLOAT(OFS_RETURN) = -4;
2223 // not conform with VM_fopen
2224 data = FS_LoadFile(filename, false);
2226 PRVM_G_FLOAT(OFS_RETURN) = -1;
2228 PRVM_ED_LoadFromFile(data);
2239 float mod(float val, float m)
2242 void VM_modulo(void)
2245 VM_SAFEPARMCOUNT(2,VM_module);
2247 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2248 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2250 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2253 //=============================================================================
2254 // Draw builtins (client & menu)
2260 float iscachedpic(string pic)
2263 void VM_iscachedpic(void)
2265 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2267 // drawq hasnt such a function, thus always return true
2268 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2275 string precache_pic(string pic)
2278 void VM_precache_pic(void)
2282 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2284 s = PRVM_G_STRING(OFS_PARM0);
2285 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2288 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2290 VM_CheckEmptyString (s);
2292 if(!Draw_CachePic(s))
2293 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2303 void VM_freepic(void)
2307 VM_SAFEPARMCOUNT(1,VM_freepic);
2309 s = PRVM_G_STRING(OFS_PARM0);
2312 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2314 VM_CheckEmptyString (s);
2323 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2326 void VM_drawcharacter(void)
2328 float *pos,*scale,*rgb;
2331 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2333 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2336 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2337 PRVM_G_FLOAT(OFS_RETURN) = -1;
2341 pos = PRVM_G_VECTOR(OFS_PARM0);
2342 scale = PRVM_G_VECTOR(OFS_PARM2);
2343 rgb = PRVM_G_VECTOR(OFS_PARM3);
2344 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2346 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2348 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2349 PRVM_G_FLOAT(OFS_RETURN) = -2;
2353 if(pos[2] || scale[2])
2354 Con_Printf("VM_drawcharacter: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2356 if(!scale[0] || !scale[1])
2358 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2359 PRVM_G_FLOAT(OFS_RETURN) = -3;
2363 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2364 PRVM_G_FLOAT(OFS_RETURN) = 1;
2371 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2374 void VM_drawstring(void)
2376 float *pos,*scale,*rgb;
2379 VM_SAFEPARMCOUNT(6,VM_drawstring);
2381 string = PRVM_G_STRING(OFS_PARM1);
2384 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2385 PRVM_G_FLOAT(OFS_RETURN) = -1;
2389 VM_CheckEmptyString(string);
2391 pos = PRVM_G_VECTOR(OFS_PARM0);
2392 scale = PRVM_G_VECTOR(OFS_PARM2);
2393 rgb = PRVM_G_VECTOR(OFS_PARM3);
2394 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2396 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2398 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2399 PRVM_G_FLOAT(OFS_RETURN) = -2;
2403 if(!scale[0] || !scale[1])
2405 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2406 PRVM_G_FLOAT(OFS_RETURN) = -3;
2410 if(pos[2] || scale[2])
2411 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
2413 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2414 PRVM_G_FLOAT(OFS_RETURN) = 1;
2420 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2423 void VM_drawpic(void)
2426 float *size, *pos, *rgb;
2429 VM_SAFEPARMCOUNT(6,VM_drawpic);
2431 pic = PRVM_G_STRING(OFS_PARM1);
2435 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2436 PRVM_G_FLOAT(OFS_RETURN) = -1;
2440 VM_CheckEmptyString (pic);
2442 // is pic cached ? no function yet for that
2445 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2446 PRVM_G_FLOAT(OFS_RETURN) = -4;
2450 pos = PRVM_G_VECTOR(OFS_PARM0);
2451 size = PRVM_G_VECTOR(OFS_PARM2);
2452 rgb = PRVM_G_VECTOR(OFS_PARM3);
2453 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2455 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2457 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2458 PRVM_G_FLOAT(OFS_RETURN) = -2;
2462 if(pos[2] || size[2])
2463 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2465 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2466 PRVM_G_FLOAT(OFS_RETURN) = 1;
2473 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2476 void VM_drawfill(void)
2478 float *size, *pos, *rgb;
2481 VM_SAFEPARMCOUNT(5,VM_drawfill);
2484 pos = PRVM_G_VECTOR(OFS_PARM0);
2485 size = PRVM_G_VECTOR(OFS_PARM1);
2486 rgb = PRVM_G_VECTOR(OFS_PARM2);
2487 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2489 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2491 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2492 PRVM_G_FLOAT(OFS_RETURN) = -2;
2496 if(pos[2] || size[2])
2497 Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
2499 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2500 PRVM_G_FLOAT(OFS_RETURN) = 1;
2507 drawsetcliparea(float x, float y, float width, float height)
2510 void VM_drawsetcliparea(void)
2513 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2515 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2516 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2517 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2518 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2520 DrawQ_SetClipArea(x,y,w,h);
2525 VM_drawresetcliparea
2530 void VM_drawresetcliparea(void)
2532 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2534 DrawQ_ResetClipArea();
2541 vector getimagesize(string pic)
2544 void VM_getimagesize(void)
2549 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2551 p = PRVM_G_STRING(OFS_PARM0);
2554 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2556 VM_CheckEmptyString (p);
2558 pic = Draw_CachePic (p);
2560 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2561 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2562 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2565 void VM_Cmd_Init(void)
2567 // only init the stuff for the current prog
2568 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
2572 void VM_Cmd_Reset(void)
2574 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2575 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2576 VM_Files_CloseAll();
2579 //============================================================================
2582 char *vm_sv_extensions =
2585 prvm_builtin_t vm_sv_builtins[] = {
2586 0 // to be consistent with the old vm
2589 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2591 void VM_SV_Cmd_Init(void)
2595 void VM_SV_Cmd_Reset(void)
2599 //============================================================================
2602 char *vm_cl_extensions =
2605 prvm_builtin_t vm_cl_builtins[] = {
2606 0 // to be consistent with the old vm
2609 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2611 void VM_CL_Cmd_Init(void)
2615 void VM_CL_Cmd_Reset(void)
2619 //============================================================================
2622 char *vm_m_extensions =
2629 setmousetarget(float target)
2632 void VM_M_setmousetarget(void)
2634 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2636 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2639 in_client_mouse = false;
2642 in_client_mouse = true;
2645 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2653 float getmousetarget
2656 void VM_M_getmousetarget(void)
2658 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2661 PRVM_G_FLOAT(OFS_RETURN) = 2;
2663 PRVM_G_FLOAT(OFS_RETURN) = 1;
2672 setkeydest(float dest)
2675 void VM_M_setkeydest(void)
2677 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2679 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2683 key_dest = key_game;
2687 key_dest = key_menu;
2691 // key_dest = key_message
2694 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2705 void VM_M_getkeydest(void)
2707 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2709 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2713 PRVM_G_FLOAT(OFS_RETURN) = 0;
2716 PRVM_G_FLOAT(OFS_RETURN) = 2;
2720 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2723 PRVM_G_FLOAT(OFS_RETURN) = 3;
2731 callfunction(...,string function_name)
2734 mfunction_t *PRVM_ED_FindFunction (const char *name);
2735 void VM_M_callfunction(void)
2741 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
2743 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
2746 PRVM_ERROR("VM_M_callfunction: null string !\n");
2748 VM_CheckEmptyString(s);
2750 func = PRVM_ED_FindFunction(s);
2753 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
2754 else if (func->first_statement < 0)
2756 // negative statements are built in functions
2757 int builtinnumber = -func->first_statement;
2758 prog->xfunction->builtinsprofile++;
2759 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
2760 prog->builtins[builtinnumber]();
2762 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
2767 PRVM_ExecuteProgram(func - prog->functions,"");
2776 float isfunction(string function_name)
2779 mfunction_t *PRVM_ED_FindFunction (const char *name);
2780 void VM_M_isfunction(void)
2785 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
2787 s = PRVM_G_STRING(OFS_PARM0);
2790 PRVM_ERROR("VM_M_isfunction: null string !\n");
2792 VM_CheckEmptyString(s);
2794 func = PRVM_ED_FindFunction(s);
2797 PRVM_G_FLOAT(OFS_RETURN) = false;
2799 PRVM_G_FLOAT(OFS_RETURN) = true;
2806 writetofile(float fhandle, entity ent)
2809 void VM_M_writetofile(void)
2814 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
2816 filenum = PRVM_G_FLOAT(OFS_PARM0);
2817 if (filenum < 0 || filenum >= MAX_VMFILES)
2819 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
2822 if (VM_FILES[filenum] == NULL)
2824 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
2828 ent = PRVM_G_EDICT(OFS_PARM1);
2831 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
2835 PRVM_ED_Write (VM_FILES[filenum], ent);
2838 prvm_builtin_t vm_m_builtins[] = {
2839 0, // to be consistent with the old vm
2840 // common builtings (mostly)
2913 0,0,0,0,0,0,0,0,// 80
2927 VM_WriteEntity, // 408
2943 VM_drawresetcliparea,
2944 VM_getimagesize,// 460
2953 VM_M_setmousetarget,
2954 VM_M_getmousetarget,
2957 VM_M_isfunction // 607
2960 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
2962 void VM_M_Cmd_Init(void)
2967 void VM_M_Cmd_Reset(void)