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, string match)
39 entity findentity(entity start, .entity field, string 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 s1, string s2)
72 string substring(string s, float start, float length)
74 string strzone(string s)
79 clientcommand(float client, string s) (for client and menu)
80 float tokenize(string s)
81 changelevel(string map)
82 localsound(string sample)
84 perhaps only : Menu : WriteMsg
85 ===============================
87 WriteByte(float data, float dest, float desto)
88 WriteChar(float data, float dest, float desto)
89 WriteShort(float data, float dest, float desto)
90 WriteLong(float data, float dest, float desto)
91 WriteAngle(float data, float dest, float desto)
92 WriteCoord(float data, float dest, float desto)
93 WriteString(string data, float dest, float desto)
94 WriteEntity(entity data, float dest, float desto)
96 Client & Menu : draw functions
97 ===============================
99 float iscachedpic(string pic)
100 string precache_pic(string pic)
102 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
103 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
104 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
105 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
109 #include "quakedef.h"
110 #include "progdefs.h"
111 #include "clprogdefs.h"
112 #include "mprogdefs.h"
114 //============================================================================
115 // nice helper macros
117 #ifndef VM_NOPARMCHECK
118 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f "wrong parameter count (" #p "expected ) !\n")
120 #define VM_SAFEPARMCOUNT(p,f)
123 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
125 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
127 #define e10 0,0,0,0,0,0,0,0,0,0
128 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
129 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
131 //============================================================================
134 // string zone mempool
135 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
137 // temp string handling
138 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
139 #define STRINGTEMP_BUFFERS 16
140 #define STRINGTEMP_LENGTH 4096
141 static char vm_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
142 static int vm_string_tempindex = 0;
145 #define MAX_QC_CVARS 128 * PRVM_MAXPROGS
146 cvar_t vm_qc_cvar[MAX_QC_CVARS];
147 int vm_currentqc_cvar;
150 #define MAX_VMFILES 256
151 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
152 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
154 qfile_t *vm_files[MAX_PRVMFILES];
156 static char *VM_GetTempString(void)
159 s = vm_string_temp[vm_string_tempindex];
160 vm_string_tempindex = (vm_string_tempindex + 1) % STRINGTEMP_BUFFERS;
164 void VM_CheckEmptyString (char *s)
167 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
170 //============================================================================
173 void VM_VarString(int first, char *out, int outlength)
179 outend = out + outlength - 1;
180 for (i = first;i < pr_argc && out < outend;i++)
182 s = PRVM_G_STRING((OFS_PARM0+i*3));
183 while (out < outend && *s)
193 returns true if the extension is supported by the server
195 checkextension(extensionname)
199 // kind of helper function
200 static qboolean checkextension(char *name)
206 for (e = prog->extensionstring;*e;e++)
213 while (*e && *e != ' ')
215 if (e - start == len)
216 if (!strncasecmp(start, name, len))
224 void VM_checkextension (void)
226 VM_SAFEPARMCOUNT(1,VM_checkextension);
228 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
235 This is a TERMINAL error, which will kill off the entire prog.
244 char string[STRINGTEMP_LENGTH];
246 VM_VarString(0, string, sizeof(string));
247 Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
250 ed = PRVM_G_EDICT(prog->self->ofs);
254 PRVM_ERROR ("%s: Program error", PRVM_NAME);
261 Dumps out self, then an error message. The program is aborted and self is
262 removed, but the level can continue.
267 void VM_objerror (void)
270 char string[STRINGTEMP_LENGTH];
272 VM_VarString(0, string, sizeof(string));
273 Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
276 ed = PRVM_G_EDICT (prog->self->ofs);
282 // objerror has to display the object fields -> else call
283 PRVM_ERROR ("VM_objecterror: self not defined !\n");
288 VM_print (actually used only by client and menu)
297 char string[STRINGTEMP_LENGTH];
299 VM_VarString(0, string, sizeof(string));
307 broadcast print to everyone on server
312 void VM_bprint (void)
314 char string[STRINGTEMP_LENGTH];
318 Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
322 VM_VarString(0, string, sizeof(string));
323 SV_BroadcastPrintf("%s", string);
328 VM_sprint (menu & client but only if server.active == true)
330 single print to a specific client
332 sprint(float clientnum,...[string])
335 void VM_sprint (void)
339 char string[STRINGTEMP_LENGTH];
341 //find client for this entity
342 clientnum = PRVM_G_FLOAT(OFS_PARM0);
343 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
345 Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
349 client = svs.clients + clientnum;
350 if (!client->netconnection)
352 VM_VarString(1, string, sizeof(string));
353 MSG_WriteChar(&client->message,svc_print);
354 MSG_WriteString(&client->message, string);
361 single print to the screen
363 centerprint(clientent, value)
366 void VM_centerprint (void)
368 char string[STRINGTEMP_LENGTH];
370 VM_VarString(0, string, sizeof(string));
371 SCR_CenterPrint(string);
378 vector normalize(vector)
381 void VM_normalize (void)
387 VM_SAFEPARMCOUNT(1,VM_normalize);
389 value1 = PRVM_G_VECTOR(OFS_PARM0);
391 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
395 newvalue[0] = newvalue[1] = newvalue[2] = 0;
399 newvalue[0] = value1[0] * new;
400 newvalue[1] = value1[1] * new;
401 newvalue[2] = value1[2] * new;
404 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
419 VM_SAFEPARMCOUNT(1,VM_vlen);
421 value1 = PRVM_G_VECTOR(OFS_PARM0);
423 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
426 PRVM_G_FLOAT(OFS_RETURN) = new;
433 float vectoyaw(vector)
436 void VM_vectoyaw (void)
441 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
443 value1 = PRVM_G_VECTOR(OFS_PARM0);
445 if (value1[1] == 0 && value1[0] == 0)
449 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
454 PRVM_G_FLOAT(OFS_RETURN) = yaw;
462 vector vectoangles(vector)
465 void VM_vectoangles (void)
471 VM_SAFEPARMCOUNT(1,VM_vectoangles);
473 value1 = PRVM_G_VECTOR(OFS_PARM0);
475 if (value1[1] == 0 && value1[0] == 0)
485 // LordHavoc: optimized a bit
488 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
492 else if (value1[1] > 0)
497 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
498 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
503 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
504 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
505 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
512 Returns a number from 0<= num < 1
517 void VM_random (void)
521 VM_SAFEPARMCOUNT(0,VM_random);
523 num = (rand ()&0x7fff) / ((float)0x7fff);
525 PRVM_G_FLOAT(OFS_RETURN) = num;
532 Each entity can have eight independant sound sources, like voice,
535 Channel 0 is an auto-allocate channel, the others override anything
536 already running on that entity/channel pair.
538 An attenuation of 0 will play full volume everywhere in the level.
539 Larger attenuations will drop off.
552 entity = G_EDICT(OFS_PARM0);
553 channel = G_FLOAT(OFS_PARM1);
554 sample = G_STRING(OFS_PARM2);
555 volume = G_FLOAT(OFS_PARM3) * 255;
556 attenuation = G_FLOAT(OFS_PARM4);
558 if (volume < 0 || volume > 255)
559 Host_Error ("SV_StartSound: volume = %i", volume);
561 if (attenuation < 0 || attenuation > 4)
562 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
564 if (channel < 0 || channel > 7)
565 Host_Error ("SV_StartSound: channel = %i", channel);
567 SV_StartSound (entity, channel, sample, volume, attenuation);
575 localsound(string sample)
578 void VM_localsound(void)
582 VM_SAFEPARMCOUNT(1,VM_localsound);
584 s = PRVM_G_STRING(OFS_PARM0);
588 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
589 PRVM_G_FLOAT(OFS_RETURN) = -4;
594 PRVM_G_FLOAT(OFS_RETURN) = 1;
606 PRVM_ERROR ("%s: break statement", PRVM_NAME);
609 //============================================================================
615 Sends text over to the client's execution buffer
617 [localcmd (string) or]
621 void VM_localcmd (void)
623 VM_SAFEPARMCOUNT(1,VM_localcmd);
625 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
637 VM_SAFEPARMCOUNT(1,VM_cvar);
639 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
646 void cvar_set (string,string)
649 void VM_cvar_set (void)
651 VM_SAFEPARMCOUNT(2,VM_cvar_set);
653 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
663 void VM_dprint (void)
665 char string[STRINGTEMP_LENGTH];
666 if (developer.integer)
668 VM_VarString(0, string, sizeof(string));
669 Con_Printf("%s: %s", PRVM_NAME, string);
686 VM_SAFEPARMCOUNT(1, VM_ftos);
688 v = PRVM_G_FLOAT(OFS_PARM0);
690 s = VM_GetTempString();
691 if ((float)((int)v) == v)
692 sprintf(s, "%i", (int)v);
695 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
710 VM_SAFEPARMCOUNT(1,VM_fabs);
712 v = PRVM_G_FLOAT(OFS_PARM0);
713 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
728 VM_SAFEPARMCOUNT(1,VM_vtos);
730 s = VM_GetTempString();
731 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]);
732 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
747 VM_SAFEPARMCOUNT(1, VM_etos);
749 s = VM_GetTempString();
750 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
751 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
758 float stof(...[string])
763 char string[STRINGTEMP_LENGTH];
764 VM_VarString(0, string, sizeof(string));
765 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
779 prog->xfunction->builtinsprofile += 20;
780 ed = PRVM_ED_Alloc();
792 void VM_remove (void)
795 prog->xfunction->builtinsprofile += 20;
797 VM_SAFEPARMCOUNT(1, VM_remove);
799 ed = PRVM_G_EDICT(OFS_PARM0);
800 // if (ed == prog->edicts)
801 // PRVM_ERROR ("remove: tried to remove world\n");
802 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
803 // Host_Error("remove: tried to remove a client\n");
811 entity find(entity start, .string field, string match)
822 VM_SAFEPARMCOUNT(3,VM_find);
824 e = PRVM_G_EDICTNUM(OFS_PARM0);
825 f = PRVM_G_INT(OFS_PARM1);
826 s = PRVM_G_STRING(OFS_PARM2);
830 // return reserved edict 0 (could be used for whatever the prog wants)
831 VM_RETURN_EDICT(prog->edicts);
835 for (e++ ; e < prog->num_edicts ; e++)
837 prog->xfunction->builtinsprofile++;
838 ed = PRVM_EDICT_NUM(e);
841 t = PRVM_E_STRING(ed,f);
851 VM_RETURN_EDICT(sv.edicts);
858 entity findfloat(entity start, .float field, string match)
859 entity findentity(entity start, .entity field, string match)
862 // LordHavoc: added this for searching float, int, and entity reference fields
863 void VM_findfloat (void)
870 VM_SAFEPARMCOUNT(3,VM_findfloat);
872 e = PRVM_G_EDICTNUM(OFS_PARM0);
873 f = PRVM_G_INT(OFS_PARM1);
874 s = PRVM_G_FLOAT(OFS_PARM2);
876 for (e++ ; e < prog->num_edicts ; e++)
878 prog->xfunction->builtinsprofile++;
879 ed = PRVM_EDICT_NUM(e);
882 if (PRVM_E_FLOAT(ed,f) == s)
889 VM_RETURN_EDICT(prog->edicts);
896 entity findchain(.string field, string match)
899 int PRVM_ED_FindFieldOffset(const char *field);
900 // chained search for strings in entity fields
901 // entity(.string field, string match) findchain = #402;
902 void VM_findchain (void)
908 prvm_edict_t *ent, *chain;
910 VM_SAFEPARMCOUNT(2,VM_findchain);
912 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
913 if(!prog->flag & PRVM_FE_CHAIN)
914 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
916 chain_of = PRVM_ED_FindFieldOffset ("chain");
918 chain = prog->edicts;
920 f = PRVM_G_INT(OFS_PARM0);
921 s = PRVM_G_STRING(OFS_PARM1);
924 VM_RETURN_EDICT(prog->edicts);
928 ent = PRVM_NEXT_EDICT(prog->edicts);
929 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
931 prog->xfunction->builtinsprofile++;
934 t = PRVM_E_STRING(ent,f);
940 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
944 VM_RETURN_EDICT(chain);
951 entity findchainfloat(.string field, float match)
952 entity findchainentity(.string field, entity match)
955 // LordHavoc: chained search for float, int, and entity reference fields
956 // entity(.string field, float match) findchainfloat = #403;
957 void VM_findchainfloat (void)
963 prvm_edict_t *ent, *chain;
965 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
967 if(!prog->flag & PRVM_FE_CHAIN)
968 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
970 chain_of = PRVM_ED_FindFieldOffset ("chain");
972 chain = (prvm_edict_t *)prog->edicts;
974 f = PRVM_G_INT(OFS_PARM0);
975 s = PRVM_G_FLOAT(OFS_PARM1);
977 ent = PRVM_NEXT_EDICT(prog->edicts);
978 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
980 prog->xfunction->builtinsprofile++;
983 if (E_FLOAT(ent,f) != s)
986 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
990 VM_RETURN_EDICT(chain);
997 string precache_file(string)
1000 void VM_precache_file (void)
1001 { // precache_file is only used to copy files with qcc, it does nothing
1002 VM_SAFEPARMCOUNT(1,VM_precache_file);
1004 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1011 used instead of the other VM_precache_* functions in the builtin list
1015 void VM_precache_error (void)
1017 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1024 string precache_sound (string sample)
1027 void VM_precache_sound (void)
1031 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1033 s = PRVM_G_STRING(OFS_PARM0);
1034 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1035 VM_CheckEmptyString (s);
1039 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1043 if(!S_PrecacheSound(s,true))
1044 Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1054 void VM_coredump (void)
1056 VM_SAFEPARMCOUNT(0,VM_coredump);
1058 PRVM_ED_PrintEdicts_f ();
1068 void VM_traceon (void)
1070 VM_SAFEPARMCOUNT(0,VM_traceon);
1082 void VM_traceoff (void)
1084 VM_SAFEPARMCOUNT(0,VM_traceoff);
1086 prog->trace = false;
1093 eprint(entity float)
1096 void VM_eprint (void)
1098 VM_SAFEPARMCOUNT(1,VM_eprint);
1100 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1114 VM_SAFEPARMCOUNT(1,VM_rint);
1116 f = PRVM_G_FLOAT(OFS_PARM0);
1118 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1120 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1130 void VM_floor (void)
1132 VM_SAFEPARMCOUNT(1,VM_floor);
1134 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1146 VM_SAFEPARMCOUNT(1,VM_ceil);
1148 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1156 entity nextent(entity)
1159 void VM_nextent (void)
1164 i = PRVM_G_EDICTNUM(OFS_PARM0);
1167 prog->xfunction->builtinsprofile++;
1169 if (i == prog->num_edicts)
1171 VM_RETURN_EDICT(prog->edicts);
1174 ent = PRVM_EDICT_NUM(i);
1177 VM_RETURN_EDICT(ent);
1184 ===============================================================================
1187 used only for client and menu
1188 severs uses VM_SV_...
1190 Write*(* data, float type, float to)
1192 ===============================================================================
1195 #define MSG_BROADCAST 0 // unreliable to all
1196 #define MSG_ONE 1 // reliable to one (msg_entity)
1197 #define MSG_ALL 2 // reliable to all
1198 #define MSG_INIT 3 // write to the init string
1200 sizebuf_t *VM_WriteDest (void)
1206 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1208 dest = G_FLOAT(OFS_PARM1);
1212 return &sv.datagram;
1215 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1216 if (!sv.active || destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1217 PRVM_ERROR("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1219 return &svs.clients[destclient].message;
1222 return &sv.reliable_datagram;
1228 PRVM_ERROR ("WriteDest: bad destination");
1235 void VM_WriteByte (void)
1237 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1240 void VM_WriteChar (void)
1242 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1245 void VM_WriteShort (void)
1247 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1250 void VM_WriteLong (void)
1252 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1255 void VM_WriteAngle (void)
1257 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1260 void VM_WriteCoord (void)
1262 MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1265 void VM_WriteString (void)
1267 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1270 void VM_WriteEntity (void)
1272 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1275 //=============================================================================
1282 changelevel(string map)
1285 void VM_changelevel (void)
1289 VM_SAFEPARMCOUNT(1, VM_changelevel);
1293 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1297 // make sure we don't issue two changelevels
1298 if (svs.changelevel_issued)
1300 svs.changelevel_issued = true;
1302 s = G_STRING(OFS_PARM0);
1303 Cbuf_AddText (va("changelevel %s\n",s));
1315 VM_SAFEPARMCOUNT(1,VM_sin);
1316 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1327 VM_SAFEPARMCOUNT(1,VM_cos);
1328 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1340 VM_SAFEPARMCOUNT(1,VM_sqrt);
1341 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1348 Returns a vector of length < 1 and > 0
1353 void VM_randomvec (void)
1358 VM_SAFEPARMCOUNT(0, VM_randomvec);
1363 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1364 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1365 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1367 while (DotProduct(temp, temp) >= 1);
1368 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1371 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1372 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1373 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1374 // length returned always > 0
1375 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1376 VectorScale(temp,length, temp);*/
1377 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1380 //=============================================================================
1386 float registercvar (string name, string value)
1389 void VM_registercvar (void)
1394 VM_SAFEPARMCOUNT(2,VM_registercvar);
1396 name = PRVM_G_STRING(OFS_PARM0);
1397 value = PRVM_G_STRING(OFS_PARM1);
1398 PRVM_G_FLOAT(OFS_RETURN) = 0;
1399 // first check to see if it has already been defined
1400 if (Cvar_FindVar (name))
1403 // check for overlap with a command
1404 if (Cmd_Exists (name))
1406 Con_Printf ("VM_registercvar: %s is a command\n", name);
1410 if (vm_currentqc_cvar >= MAX_QC_CVARS)
1411 PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1413 // copy the name and value
1414 variable = &vm_qc_cvar[vm_currentqc_cvar++];
1415 variable->name = Z_Malloc (strlen(name)+1);
1416 strcpy (variable->name, name);
1417 variable->string = Z_Malloc (strlen(value)+1);
1418 strcpy (variable->string, value);
1419 variable->value = atof (value);
1421 Cvar_RegisterVariable(variable);
1422 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1429 returns the minimum of two supplied floats
1431 float min(float a, float b, ...[float])
1436 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1437 if (prog->argc == 2)
1438 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1439 else if (prog->argc >= 3)
1442 float f = PRVM_G_FLOAT(OFS_PARM0);
1443 for (i = 1;i < prog->argc;i++)
1444 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1445 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1446 PRVM_G_FLOAT(OFS_RETURN) = f;
1449 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1456 returns the maximum of two supplied floats
1458 float max(float a, float b, ...[float])
1463 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1465 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1466 else if (pr_argc >= 3)
1469 float f = PRVM_G_FLOAT(OFS_PARM0);
1470 for (i = 1;i < pr_argc;i++)
1471 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1472 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1473 G_FLOAT(OFS_RETURN) = f;
1476 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1483 returns number bounded by supplied range
1485 float bound(float min, float value, float max)
1488 void VM_bound (void)
1490 VM_SAFEPARMCOUNT(3,VM_bound);
1491 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1498 returns a raised to power b
1500 float pow(float a, float b)
1505 VM_SAFEPARMCOUNT(2,VM_pow);
1506 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1513 copies data from one entity to another
1515 copyentity(entity src, entity dst)
1518 void VM_copyentity (void)
1520 prvm_edict_t *in, *out;
1521 VM_SAFEPARMCOUNT(2,VM_copyentity);
1522 in = PRVM_G_EDICT(OFS_PARM0);
1523 out = PRVM_G_EDICT(OFS_PARM1);
1524 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1531 sets the color of a client and broadcasts the update to all connected clients
1533 setcolor(clientent, value)
1536 /*void PF_setcolor (void)
1542 entnum = G_EDICTNUM(OFS_PARM0);
1543 i = G_FLOAT(OFS_PARM1);
1545 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1547 Con_Printf ("tried to setcolor a non-client\n");
1551 client = svs.clients + entnum-1;
1552 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1555 client->old_colors = i;
1556 client->edict->v->team = (i & 15) + 1;
1558 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1559 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1560 MSG_WriteByte (&sv.reliable_datagram, i);
1563 void VM_Files_Init(void)
1565 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1568 void VM_Files_CloseAll(void)
1571 for (i = 0;i < MAX_VMFILES;i++)
1574 FS_Close(VM_FILES[i]);
1575 //VM_FILES[i] = NULL;
1577 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1584 float fopen(string filename, float mode)
1587 // float(string filename, float mode) fopen = #110;
1588 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1589 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1593 char *modestring, *filename;
1595 VM_SAFEPARMCOUNT(2,VM_fopen);
1597 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1598 if (VM_FILES[filenum] == NULL)
1600 if (filenum >= MAX_VMFILES)
1602 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1603 PRVM_G_FLOAT(OFS_RETURN) = -2;
1606 mode = PRVM_G_FLOAT(OFS_PARM1);
1609 case 0: // FILE_READ
1612 case 1: // FILE_APPEND
1615 case 2: // FILE_WRITE
1619 Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1620 PRVM_G_FLOAT(OFS_RETURN) = -3;
1623 filename = PRVM_G_STRING(OFS_PARM0);
1624 // .. is parent directory on many platforms
1625 // / is parent directory on Amiga
1626 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1627 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1628 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1630 Con_Printf("VM_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
1631 PRVM_G_FLOAT(OFS_RETURN) = -4;
1634 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1635 if (VM_FILES[filenum] == NULL)
1636 PRVM_G_FLOAT(OFS_RETURN) = -1;
1638 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1645 fclose(float fhandle)
1648 //void(float fhandle) fclose = #111; // closes a file
1649 void VM_fclose(void)
1653 VM_SAFEPARMCOUNT(1,VM_fclose);
1655 filenum = PRVM_G_FLOAT(OFS_PARM0);
1656 if (filenum < 0 || filenum >= MAX_VMFILES)
1658 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1661 if (VM_FILES[filenum] == NULL)
1663 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1666 FS_Close(VM_FILES[filenum]);
1667 VM_FILES[filenum] = NULL;
1674 string fgets(float fhandle)
1677 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1681 static char string[STRINGTEMP_LENGTH];
1684 VM_SAFEPARMCOUNT(1,VM_fgets);
1686 filenum = PRVM_G_FLOAT(OFS_PARM0);
1687 if (filenum < 0 || filenum >= MAX_VMFILES)
1689 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1692 if (VM_FILES[filenum] == NULL)
1694 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1700 c = FS_Getc(VM_FILES[filenum]);
1701 if (c == '\r' || c == '\n' || c < 0)
1703 if (end < STRINGTEMP_LENGTH - 1)
1707 // remove \n following \r
1709 c = FS_Getc(VM_FILES[filenum]);
1710 if (developer.integer)
1711 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1713 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1715 PRVM_G_INT(OFS_RETURN) = 0;
1722 fputs(float fhandle, string s)
1725 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1729 char string[STRINGTEMP_LENGTH];
1732 VM_SAFEPARMCOUNT(2,VM_fputs);
1734 filenum = PRVM_G_FLOAT(OFS_PARM0);
1735 if (filenum < 0 || filenum >= MAX_VMFILES)
1737 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1740 if (VM_FILES[filenum] == NULL)
1742 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1745 VM_VarString(1, string, sizeof(string));
1746 if ((stringlength = strlen(string)))
1747 FS_Write(VM_FILES[filenum], string, stringlength);
1748 if (developer.integer)
1749 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1756 float strlen(string s)
1759 //float(string s) strlen = #114; // returns how many characters are in a string
1760 void VM_strlen(void)
1764 VM_SAFEPARMCOUNT(1,VM_strlen);
1766 s = PRVM_G_STRING(OFS_PARM0);
1768 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1770 PRVM_G_FLOAT(OFS_RETURN) = 0;
1777 string strcat(string s1, string s2)
1780 //string(string s1, string s2) strcat = #115;
1781 // concatenates two strings (for example "abc", "def" would return "abcdef")
1782 // and returns as a tempstring
1783 void VM_strcat(void)
1787 VM_SAFEPARMCOUNT(2,VM_strcat);
1789 s = VM_GetTempString();
1790 VM_VarString(0, s, STRINGTEMP_LENGTH);
1791 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1798 string substring(string s, float start, float length)
1801 // string(string s, float start, float length) substring = #116;
1802 // returns a section of a string as a tempstring
1803 void VM_substring(void)
1805 int i, start, length;
1808 VM_SAFEPARMCOUNT(3,VM_substring);
1810 string = VM_GetTempString();
1811 s = PRVM_G_STRING(OFS_PARM0);
1812 start = PRVM_G_FLOAT(OFS_PARM1);
1813 length = PRVM_G_FLOAT(OFS_PARM2);
1816 for (i = 0;i < start && *s;i++, s++);
1817 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1820 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1827 vector stov(string s)
1830 //vector(string s) stov = #117; // returns vector value from a string
1833 char string[STRINGTEMP_LENGTH];
1835 VM_SAFEPARMCOUNT(1,VM_stov);
1837 VM_VarString(0, string, sizeof(string));
1838 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1845 string strzone(string s)
1848 //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)
1849 void VM_strzone(void)
1853 VM_SAFEPARMCOUNT(1,VM_strzone);
1855 in = PRVM_G_STRING(OFS_PARM0);
1856 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1858 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1868 //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!!!)
1869 void VM_strunzone(void)
1871 VM_SAFEPARMCOUNT(1,VM_strunzone);
1873 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1878 VM_command (used by client and menu)
1880 clientcommand(float client, string s) (for client and menu)
1883 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1884 //this function originally written by KrimZon, made shorter by LordHavoc
1885 void VM_clcommand (void)
1887 client_t *temp_client;
1890 VM_SAFEPARMCOUNT(2,VM_clcommand);
1892 i = PRVM_G_FLOAT(OFS_PARM0);
1893 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1895 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1899 temp_client = host_client;
1900 host_client = svs.clients + i;
1901 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1902 host_client = temp_client;
1910 float tokenize(string s)
1913 //float(string s) tokenize = #441;
1914 // takes apart a string into individal words (access them with argv), returns how many
1915 // this function originally written by KrimZon, made shorter by LordHavoc
1916 static char **tokens = NULL;
1917 static int max_tokens, num_tokens = 0;
1918 void VM_tokenize (void)
1923 VM_SAFEPARMCOUNT(1,VM_tokenize);
1925 str = PRVM_G_STRING(OFS_PARM0);
1930 for (i=0;i<num_tokens;i++)
1936 tokens = Z_Malloc(strlen(str) * sizeof(char *));
1937 max_tokens = strlen(str);
1939 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
1941 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
1942 strcpy(tokens[num_tokens], com_token);
1945 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
1952 string argv(float n)
1955 //string(float n) argv = #442;
1956 // returns a word from the tokenized string (returns nothing for an invalid index)
1957 // this function originally written by KrimZon, made shorter by LordHavoc
1962 VM_SAFEPARMCOUNT(1,VM_argv);
1964 token_num = PRVM_G_FLOAT(OFS_PARM0);
1965 if (token_num >= 0 && token_num < num_tokens)
1966 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
1968 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
1972 //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)
1973 void PF_setattachment (void)
1975 edict_t *e = G_EDICT(OFS_PARM0);
1976 edict_t *tagentity = G_EDICT(OFS_PARM1);
1977 char *tagname = G_STRING(OFS_PARM2);
1982 if (tagentity == NULL)
1983 tagentity = sv.edicts;
1985 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
1987 v->edict = EDICT_TO_PROG(tagentity);
1989 v = GETEDICTFIELDVALUE(e, eval_tag_index);
1992 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
1994 modelindex = (int)tagentity->v->modelindex;
1995 if (modelindex >= 0 && modelindex < MAX_MODELS)
1997 model = sv.models[modelindex];
1998 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
1999 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2000 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2002 if (v->_float == 0 && model->alias.aliasnum_tags)
2003 for (i = 0;i < model->alias.aliasnum_tags;i++)
2004 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2007 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);
2010 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));
2021 void VM_isserver(void)
2023 VM_SAFEPARMCOUNT(0,VM_serverstate);
2025 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2035 void VM_clientcount(void)
2037 VM_SAFEPARMCOUNT(0,VM_clientcount);
2039 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2049 void VM_clientstate(void)
2051 VM_SAFEPARMCOUNT(0,VM_clientstate);
2053 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2056 //=============================================================================
2057 // Draw builtins (client & menu)
2063 float iscachedpic(string pic)
2066 void VM_iscachedpic(void)
2068 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2070 // drawq hasnt such a function, thus always return true
2071 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2078 string precache_pic(string pic)
2081 void VM_precache_pic(void)
2085 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2087 s = PRVM_G_STRING(OFS_PARM0);
2088 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2091 PRVM_ERROR ("VM_precache_pic: %s: NULL\n");
2093 VM_CheckEmptyString (s);
2105 void VM_freepic(void)
2109 VM_SAFEPARMCOUNT(1,VM_freepic);
2111 s = PRVM_G_STRING(OFS_PARM0);
2114 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2116 VM_CheckEmptyString (s);
2125 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2128 void VM_drawcharacter(void)
2130 float *pos,*scale,*rgb;
2133 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2135 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2138 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2139 PRVM_G_FLOAT(OFS_RETURN) = -1;
2143 pos = PRVM_G_VECTOR(OFS_PARM0);
2144 scale = PRVM_G_VECTOR(OFS_PARM2);
2145 rgb = PRVM_G_VECTOR(OFS_PARM3);
2146 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2148 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2150 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2151 PRVM_G_FLOAT(OFS_RETURN) = -2;
2155 if(pos[2] || scale[2])
2156 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")));
2158 if(!scale[0] || !scale[1])
2160 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2161 PRVM_G_FLOAT(OFS_RETURN) = -3;
2165 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2166 PRVM_G_FLOAT(OFS_RETURN) = 1;
2173 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2176 void VM_drawstring(void)
2178 float *pos,*scale,*rgb;
2181 VM_SAFEPARMCOUNT(6,VM_drawstring);
2183 string = PRVM_G_STRING(OFS_PARM1);
2186 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2187 PRVM_G_FLOAT(OFS_RETURN) = -1;
2191 VM_CheckEmptyString(string);
2193 pos = PRVM_G_VECTOR(OFS_PARM0);
2194 scale = PRVM_G_VECTOR(OFS_PARM2);
2195 rgb = PRVM_G_VECTOR(OFS_PARM3);
2196 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2198 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2200 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2201 PRVM_G_FLOAT(OFS_RETURN) = -2;
2205 if(!scale[0] || !scale[1])
2207 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2208 PRVM_G_FLOAT(OFS_RETURN) = -3;
2212 if(pos[2] || scale[2])
2213 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")));
2215 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2216 PRVM_G_FLOAT(OFS_RETURN) = 1;
2222 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2225 void VM_drawpic(void)
2228 float *size, *pos, *rgb;
2231 VM_SAFEPARMCOUNT(6,VM_drawpic);
2233 pic = PRVM_G_STRING(OFS_PARM1);
2237 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2238 PRVM_G_FLOAT(OFS_RETURN) = -1;
2242 VM_CheckEmptyString (pic);
2247 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2248 PRVM_G_FLOAT(OFS_RETURN) = -4;
2252 pos = PRVM_G_VECTOR(OFS_PARM0);
2253 size = PRVM_G_VECTOR(OFS_PARM2);
2254 rgb = PRVM_G_VECTOR(OFS_PARM3);
2255 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2257 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2259 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2260 PRVM_G_FLOAT(OFS_RETURN) = -2;
2264 if(pos[2] || size[2])
2265 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")));
2267 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2268 PRVM_G_FLOAT(OFS_RETURN) = 1;
2275 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2278 void VM_drawfill(void)
2280 float *size, *pos, *rgb;
2283 VM_SAFEPARMCOUNT(5,VM_drawfill);
2286 pos = PRVM_G_VECTOR(OFS_PARM0);
2287 size = PRVM_G_VECTOR(OFS_PARM1);
2288 rgb = PRVM_G_VECTOR(OFS_PARM2);
2289 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2291 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2293 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2294 PRVM_G_FLOAT(OFS_RETURN) = -2;
2298 if(pos[2] || size[2])
2299 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")));
2301 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2302 PRVM_G_FLOAT(OFS_RETURN) = 1;
2305 void VM_Cmd_Init(void)
2307 // only init the stuff for the current prog
2308 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
2312 void VM_Cmd_Reset(void)
2314 Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2315 VM_Files_CloseAll();
2318 //============================================================================
2321 char *vm_sv_extensions =
2324 prvm_builtin_t vm_sv_builtins[] = {
2325 0 // to be consistent with the old vm
2328 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2330 void VM_SV_Cmd_Init(void)
2334 void VM_SV_Cmd_Reset(void)
2338 //============================================================================
2341 char *vm_cl_extensions =
2344 prvm_builtin_t vm_cl_builtins[] = {
2345 0 // to be consistent with the old vm
2348 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2350 void VM_CL_Cmd_Init(void)
2354 void VM_CL_Cmd_Reset(void)
2358 //============================================================================
2361 char *vm_m_extensions =
2364 // void setkeydest(float dest)
2365 void VM_M_setkeydest(void)
2367 VM_SAFEPARMCOUNT(1,VM_M_SetKeyDest);
2369 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2373 key_dest = key_game;
2377 key_dest = key_menu;
2381 // key_dest = key_message
2384 PRVM_ERROR("VM_M_SetKeyDest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2390 // float getkeydest(void)
2391 void VM_M_getkeydest(void)
2393 VM_SAFEPARMCOUNT(0,VM_M_GetKeyDest);
2395 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2399 PRVM_G_FLOAT(OFS_RETURN) = 0;
2402 PRVM_G_FLOAT(OFS_RETURN) = 2;
2406 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2409 PRVM_G_FLOAT(OFS_RETURN) = 3;
2413 prvm_builtin_t vm_m_builtins[] = {
2414 0, // to be consistent with the old vm
2415 // common builtings (mostly)
2475 VM_clientstate, // 60
2479 VM_localsound, // 64
2527 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
2529 void VM_M_Cmd_Init(void)
2534 void VM_M_Cmd_Reset(void)