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 perhaps only : Menu : WriteMsg
87 ===============================
89 WriteByte(float data, float dest, float desto)
90 WriteChar(float data, float dest, float desto)
91 WriteShort(float data, float dest, float desto)
92 WriteLong(float data, float dest, float desto)
93 WriteAngle(float data, float dest, float desto)
94 WriteCoord(float data, float dest, float desto)
95 WriteString(string data, float dest, float desto)
96 WriteEntity(entity data, float dest, float desto)
98 Client & Menu : draw functions
99 ===============================
101 float iscachedpic(string pic)
102 string precache_pic(string pic)
104 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
105 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
106 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
107 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
110 ==============================================================================
114 setkeydest(float dest)
116 setmousetarget(float target)
117 float getmousetarget(void)
120 #include "quakedef.h"
121 #include "progdefs.h"
122 #include "clprogdefs.h"
123 #include "mprogdefs.h"
125 //============================================================================
126 // nice helper macros
128 #ifndef VM_NOPARMCHECK
129 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
131 #define VM_SAFEPARMCOUNT(p,f)
134 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
136 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
138 #define e10 0,0,0,0,0,0,0,0,0,0
139 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
140 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
142 //============================================================================
145 // string zone mempool
146 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
148 // temp string handling
149 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
150 #define STRINGTEMP_BUFFERS 16
151 #define STRINGTEMP_LENGTH 4096
152 static char vm_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
153 static int vm_string_tempindex = 0;
156 #define MAX_QC_CVARS 128 * PRVM_MAXPROGS
157 cvar_t vm_qc_cvar[MAX_QC_CVARS];
158 int vm_currentqc_cvar;
161 #define MAX_VMFILES 256
162 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
163 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
165 qfile_t *vm_files[MAX_PRVMFILES];
167 static char *VM_GetTempString(void)
170 s = vm_string_temp[vm_string_tempindex];
171 vm_string_tempindex = (vm_string_tempindex + 1) % STRINGTEMP_BUFFERS;
175 void VM_CheckEmptyString (char *s)
178 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
181 //============================================================================
184 void VM_VarString(int first, char *out, int outlength)
190 outend = out + outlength - 1;
191 for (i = first;i < prog->argc && out < outend;i++)
193 s = PRVM_G_STRING((OFS_PARM0+i*3));
194 while (out < outend && *s)
204 returns true if the extension is supported by the server
206 checkextension(extensionname)
210 // kind of helper function
211 static qboolean checkextension(char *name)
217 for (e = prog->extensionstring;*e;e++)
224 while (*e && *e != ' ')
226 if (e - start == len)
227 if (!strncasecmp(start, name, len))
235 void VM_checkextension (void)
237 VM_SAFEPARMCOUNT(1,VM_checkextension);
239 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
246 This is a TERMINAL error, which will kill off the entire prog.
255 char string[STRINGTEMP_LENGTH];
257 VM_VarString(0, string, sizeof(string));
258 Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
261 ed = PRVM_G_EDICT(prog->self->ofs);
265 PRVM_ERROR ("%s: Program error", PRVM_NAME);
272 Dumps out self, then an error message. The program is aborted and self is
273 removed, but the level can continue.
278 void VM_objerror (void)
281 char string[STRINGTEMP_LENGTH];
283 VM_VarString(0, string, sizeof(string));
284 Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
287 ed = PRVM_G_EDICT (prog->self->ofs);
293 // objerror has to display the object fields -> else call
294 PRVM_ERROR ("VM_objecterror: self not defined !\n");
299 VM_print (actually used only by client and menu)
308 char string[STRINGTEMP_LENGTH];
310 VM_VarString(0, string, sizeof(string));
318 broadcast print to everyone on server
323 void VM_bprint (void)
325 char string[STRINGTEMP_LENGTH];
329 Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
333 VM_VarString(0, string, sizeof(string));
334 SV_BroadcastPrintf("%s", string);
339 VM_sprint (menu & client but only if server.active == true)
341 single print to a specific client
343 sprint(float clientnum,...[string])
346 void VM_sprint (void)
350 char string[STRINGTEMP_LENGTH];
352 //find client for this entity
353 clientnum = PRVM_G_FLOAT(OFS_PARM0);
354 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
356 Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
360 client = svs.clients + clientnum;
361 if (!client->netconnection)
363 VM_VarString(1, string, sizeof(string));
364 MSG_WriteChar(&client->message,svc_print);
365 MSG_WriteString(&client->message, string);
372 single print to the screen
374 centerprint(clientent, value)
377 void VM_centerprint (void)
379 char string[STRINGTEMP_LENGTH];
381 VM_VarString(0, string, sizeof(string));
382 SCR_CenterPrint(string);
389 vector normalize(vector)
392 void VM_normalize (void)
398 VM_SAFEPARMCOUNT(1,VM_normalize);
400 value1 = PRVM_G_VECTOR(OFS_PARM0);
402 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
406 newvalue[0] = newvalue[1] = newvalue[2] = 0;
410 newvalue[0] = value1[0] * new;
411 newvalue[1] = value1[1] * new;
412 newvalue[2] = value1[2] * new;
415 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
430 VM_SAFEPARMCOUNT(1,VM_vlen);
432 value1 = PRVM_G_VECTOR(OFS_PARM0);
434 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
437 PRVM_G_FLOAT(OFS_RETURN) = new;
444 float vectoyaw(vector)
447 void VM_vectoyaw (void)
452 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
454 value1 = PRVM_G_VECTOR(OFS_PARM0);
456 if (value1[1] == 0 && value1[0] == 0)
460 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
465 PRVM_G_FLOAT(OFS_RETURN) = yaw;
473 vector vectoangles(vector)
476 void VM_vectoangles (void)
482 VM_SAFEPARMCOUNT(1,VM_vectoangles);
484 value1 = PRVM_G_VECTOR(OFS_PARM0);
486 if (value1[1] == 0 && value1[0] == 0)
496 // LordHavoc: optimized a bit
499 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
503 else if (value1[1] > 0)
508 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
509 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
514 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
515 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
516 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
523 Returns a number from 0<= num < 1
528 void VM_random (void)
532 VM_SAFEPARMCOUNT(0,VM_random);
534 num = (rand ()&0x7fff) / ((float)0x7fff);
536 PRVM_G_FLOAT(OFS_RETURN) = num;
543 Each entity can have eight independant sound sources, like voice,
546 Channel 0 is an auto-allocate channel, the others override anything
547 already running on that entity/channel pair.
549 An attenuation of 0 will play full volume everywhere in the level.
550 Larger attenuations will drop off.
563 entity = G_EDICT(OFS_PARM0);
564 channel = G_FLOAT(OFS_PARM1);
565 sample = G_STRING(OFS_PARM2);
566 volume = G_FLOAT(OFS_PARM3) * 255;
567 attenuation = G_FLOAT(OFS_PARM4);
569 if (volume < 0 || volume > 255)
570 Host_Error ("SV_StartSound: volume = %i", volume);
572 if (attenuation < 0 || attenuation > 4)
573 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
575 if (channel < 0 || channel > 7)
576 Host_Error ("SV_StartSound: channel = %i", channel);
578 SV_StartSound (entity, channel, sample, volume, attenuation);
586 localsound(string sample)
589 void VM_localsound(void)
593 VM_SAFEPARMCOUNT(1,VM_localsound);
595 s = PRVM_G_STRING(OFS_PARM0);
599 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
600 PRVM_G_FLOAT(OFS_RETURN) = -4;
605 PRVM_G_FLOAT(OFS_RETURN) = 1;
617 PRVM_ERROR ("%s: break statement", PRVM_NAME);
620 //============================================================================
626 Sends text over to the client's execution buffer
628 [localcmd (string) or]
632 void VM_localcmd (void)
634 VM_SAFEPARMCOUNT(1,VM_localcmd);
636 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
648 VM_SAFEPARMCOUNT(1,VM_cvar);
650 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
657 void cvar_set (string,string)
660 void VM_cvar_set (void)
662 VM_SAFEPARMCOUNT(2,VM_cvar_set);
664 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
674 void VM_dprint (void)
676 char string[STRINGTEMP_LENGTH];
677 if (developer.integer)
679 VM_VarString(0, string, sizeof(string));
680 Con_Printf("%s: %s", PRVM_NAME, string);
697 VM_SAFEPARMCOUNT(1, VM_ftos);
699 v = PRVM_G_FLOAT(OFS_PARM0);
701 s = VM_GetTempString();
702 if ((float)((int)v) == v)
703 sprintf(s, "%i", (int)v);
706 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
721 VM_SAFEPARMCOUNT(1,VM_fabs);
723 v = PRVM_G_FLOAT(OFS_PARM0);
724 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
739 VM_SAFEPARMCOUNT(1,VM_vtos);
741 s = VM_GetTempString();
742 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]);
743 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
758 VM_SAFEPARMCOUNT(1, VM_etos);
760 s = VM_GetTempString();
761 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
762 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
769 float stof(...[string])
774 char string[STRINGTEMP_LENGTH];
775 VM_VarString(0, string, sizeof(string));
776 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
790 prog->xfunction->builtinsprofile += 20;
791 ed = PRVM_ED_Alloc();
803 void VM_remove (void)
806 prog->xfunction->builtinsprofile += 20;
808 VM_SAFEPARMCOUNT(1, VM_remove);
810 ed = PRVM_G_EDICT(OFS_PARM0);
811 // if (ed == prog->edicts)
812 // PRVM_ERROR ("remove: tried to remove world\n");
813 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
814 // Host_Error("remove: tried to remove a client\n");
822 entity find(entity start, .string field, string match)
833 VM_SAFEPARMCOUNT(3,VM_find);
835 e = PRVM_G_EDICTNUM(OFS_PARM0);
836 f = PRVM_G_INT(OFS_PARM1);
837 s = PRVM_G_STRING(OFS_PARM2);
841 // return reserved edict 0 (could be used for whatever the prog wants)
842 VM_RETURN_EDICT(prog->edicts);
846 for (e++ ; e < prog->num_edicts ; e++)
848 prog->xfunction->builtinsprofile++;
849 ed = PRVM_EDICT_NUM(e);
852 t = PRVM_E_STRING(ed,f);
862 VM_RETURN_EDICT(sv.edicts);
869 entity findfloat(entity start, .float field, float match)
870 entity findentity(entity start, .entity field, entity match)
873 // LordHavoc: added this for searching float, int, and entity reference fields
874 void VM_findfloat (void)
881 VM_SAFEPARMCOUNT(3,VM_findfloat);
883 e = PRVM_G_EDICTNUM(OFS_PARM0);
884 f = PRVM_G_INT(OFS_PARM1);
885 s = PRVM_G_FLOAT(OFS_PARM2);
887 for (e++ ; e < prog->num_edicts ; e++)
889 prog->xfunction->builtinsprofile++;
890 ed = PRVM_EDICT_NUM(e);
893 if (PRVM_E_FLOAT(ed,f) == s)
900 VM_RETURN_EDICT(prog->edicts);
907 entity findchain(.string field, string match)
910 int PRVM_ED_FindFieldOffset(const char *field);
911 // chained search for strings in entity fields
912 // entity(.string field, string match) findchain = #402;
913 void VM_findchain (void)
919 prvm_edict_t *ent, *chain;
921 VM_SAFEPARMCOUNT(2,VM_findchain);
923 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
924 if(!prog->flag & PRVM_FE_CHAIN)
925 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
927 chain_of = PRVM_ED_FindFieldOffset ("chain");
929 chain = prog->edicts;
931 f = PRVM_G_INT(OFS_PARM0);
932 s = PRVM_G_STRING(OFS_PARM1);
935 VM_RETURN_EDICT(prog->edicts);
939 ent = PRVM_NEXT_EDICT(prog->edicts);
940 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
942 prog->xfunction->builtinsprofile++;
945 t = PRVM_E_STRING(ent,f);
951 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
955 VM_RETURN_EDICT(chain);
962 entity findchainfloat(.string field, float match)
963 entity findchainentity(.string field, entity match)
966 // LordHavoc: chained search for float, int, and entity reference fields
967 // entity(.string field, float match) findchainfloat = #403;
968 void VM_findchainfloat (void)
974 prvm_edict_t *ent, *chain;
976 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
978 if(!prog->flag & PRVM_FE_CHAIN)
979 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
981 chain_of = PRVM_ED_FindFieldOffset ("chain");
983 chain = (prvm_edict_t *)prog->edicts;
985 f = PRVM_G_INT(OFS_PARM0);
986 s = PRVM_G_FLOAT(OFS_PARM1);
988 ent = PRVM_NEXT_EDICT(prog->edicts);
989 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
991 prog->xfunction->builtinsprofile++;
994 if (E_FLOAT(ent,f) != s)
997 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1001 VM_RETURN_EDICT(chain);
1008 string precache_file(string)
1011 void VM_precache_file (void)
1012 { // precache_file is only used to copy files with qcc, it does nothing
1013 VM_SAFEPARMCOUNT(1,VM_precache_file);
1015 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1022 used instead of the other VM_precache_* functions in the builtin list
1026 void VM_precache_error (void)
1028 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1035 string precache_sound (string sample)
1038 void VM_precache_sound (void)
1042 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1044 s = PRVM_G_STRING(OFS_PARM0);
1045 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1046 VM_CheckEmptyString (s);
1050 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1054 if(!S_PrecacheSound(s,true))
1055 Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1065 void VM_coredump (void)
1067 VM_SAFEPARMCOUNT(0,VM_coredump);
1069 PRVM_ED_PrintEdicts_f ();
1079 void VM_traceon (void)
1081 VM_SAFEPARMCOUNT(0,VM_traceon);
1093 void VM_traceoff (void)
1095 VM_SAFEPARMCOUNT(0,VM_traceoff);
1097 prog->trace = false;
1107 void VM_eprint (void)
1109 VM_SAFEPARMCOUNT(1,VM_eprint);
1111 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1125 VM_SAFEPARMCOUNT(1,VM_rint);
1127 f = PRVM_G_FLOAT(OFS_PARM0);
1129 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1131 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1141 void VM_floor (void)
1143 VM_SAFEPARMCOUNT(1,VM_floor);
1145 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1157 VM_SAFEPARMCOUNT(1,VM_ceil);
1159 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1167 entity nextent(entity)
1170 void VM_nextent (void)
1175 i = PRVM_G_EDICTNUM(OFS_PARM0);
1178 prog->xfunction->builtinsprofile++;
1180 if (i == prog->num_edicts)
1182 VM_RETURN_EDICT(prog->edicts);
1185 ent = PRVM_EDICT_NUM(i);
1188 VM_RETURN_EDICT(ent);
1195 ===============================================================================
1198 used only for client and menu
1199 severs uses VM_SV_...
1201 Write*(* data, float type, float to)
1203 ===============================================================================
1206 #define MSG_BROADCAST 0 // unreliable to all
1207 #define MSG_ONE 1 // reliable to one (msg_entity)
1208 #define MSG_ALL 2 // reliable to all
1209 #define MSG_INIT 3 // write to the init string
1211 sizebuf_t *VM_WriteDest (void)
1217 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1219 dest = G_FLOAT(OFS_PARM1);
1223 return &sv.datagram;
1226 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1227 if (!sv.active || destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1228 PRVM_ERROR("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1230 return &svs.clients[destclient].message;
1233 return &sv.reliable_datagram;
1239 PRVM_ERROR ("WriteDest: bad destination");
1246 void VM_WriteByte (void)
1248 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1251 void VM_WriteChar (void)
1253 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1256 void VM_WriteShort (void)
1258 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1261 void VM_WriteLong (void)
1263 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1266 void VM_WriteAngle (void)
1268 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1271 void VM_WriteCoord (void)
1273 MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1276 void VM_WriteString (void)
1278 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1281 void VM_WriteEntity (void)
1283 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1286 //=============================================================================
1293 changelevel(string map)
1296 void VM_changelevel (void)
1300 VM_SAFEPARMCOUNT(1, VM_changelevel);
1304 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1308 // make sure we don't issue two changelevels
1309 if (svs.changelevel_issued)
1311 svs.changelevel_issued = true;
1313 s = G_STRING(OFS_PARM0);
1314 Cbuf_AddText (va("changelevel %s\n",s));
1326 VM_SAFEPARMCOUNT(1,VM_sin);
1327 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1338 VM_SAFEPARMCOUNT(1,VM_cos);
1339 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1351 VM_SAFEPARMCOUNT(1,VM_sqrt);
1352 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1359 Returns a vector of length < 1 and > 0
1364 void VM_randomvec (void)
1369 VM_SAFEPARMCOUNT(0, VM_randomvec);
1374 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1375 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1376 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1378 while (DotProduct(temp, temp) >= 1);
1379 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1382 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1383 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1384 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1385 // length returned always > 0
1386 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1387 VectorScale(temp,length, temp);*/
1388 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1391 //=============================================================================
1397 float registercvar (string name, string value)
1400 void VM_registercvar (void)
1405 VM_SAFEPARMCOUNT(2,VM_registercvar);
1407 name = PRVM_G_STRING(OFS_PARM0);
1408 value = PRVM_G_STRING(OFS_PARM1);
1409 PRVM_G_FLOAT(OFS_RETURN) = 0;
1410 // first check to see if it has already been defined
1411 if (Cvar_FindVar (name))
1414 // check for overlap with a command
1415 if (Cmd_Exists (name))
1417 Con_Printf ("VM_registercvar: %s is a command\n", name);
1421 if (vm_currentqc_cvar >= MAX_QC_CVARS)
1422 PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1424 // copy the name and value
1425 variable = &vm_qc_cvar[vm_currentqc_cvar++];
1426 variable->name = Z_Malloc (strlen(name)+1);
1427 strcpy (variable->name, name);
1428 variable->string = Z_Malloc (strlen(value)+1);
1429 strcpy (variable->string, value);
1430 variable->value = atof (value);
1432 Cvar_RegisterVariable(variable);
1433 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1440 returns the minimum of two supplied floats
1442 float min(float a, float b, ...[float])
1447 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1448 if (prog->argc == 2)
1449 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1450 else if (prog->argc >= 3)
1453 float f = PRVM_G_FLOAT(OFS_PARM0);
1454 for (i = 1;i < prog->argc;i++)
1455 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1456 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1457 PRVM_G_FLOAT(OFS_RETURN) = f;
1460 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1467 returns the maximum of two supplied floats
1469 float max(float a, float b, ...[float])
1474 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1475 if (prog->argc == 2)
1476 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1477 else if (prog->argc >= 3)
1480 float f = PRVM_G_FLOAT(OFS_PARM0);
1481 for (i = 1;i < prog->argc;i++)
1482 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1483 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1484 G_FLOAT(OFS_RETURN) = f;
1487 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1494 returns number bounded by supplied range
1496 float bound(float min, float value, float max)
1499 void VM_bound (void)
1501 VM_SAFEPARMCOUNT(3,VM_bound);
1502 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1509 returns a raised to power b
1511 float pow(float a, float b)
1516 VM_SAFEPARMCOUNT(2,VM_pow);
1517 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1524 copies data from one entity to another
1526 copyentity(entity src, entity dst)
1529 void VM_copyentity (void)
1531 prvm_edict_t *in, *out;
1532 VM_SAFEPARMCOUNT(2,VM_copyentity);
1533 in = PRVM_G_EDICT(OFS_PARM0);
1534 out = PRVM_G_EDICT(OFS_PARM1);
1535 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1542 sets the color of a client and broadcasts the update to all connected clients
1544 setcolor(clientent, value)
1547 /*void PF_setcolor (void)
1553 entnum = G_EDICTNUM(OFS_PARM0);
1554 i = G_FLOAT(OFS_PARM1);
1556 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1558 Con_Printf ("tried to setcolor a non-client\n");
1562 client = svs.clients + entnum-1;
1563 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1566 client->old_colors = i;
1567 client->edict->v->team = (i & 15) + 1;
1569 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1570 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1571 MSG_WriteByte (&sv.reliable_datagram, i);
1574 void VM_Files_Init(void)
1576 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1579 void VM_Files_CloseAll(void)
1582 for (i = 0;i < MAX_VMFILES;i++)
1585 FS_Close(VM_FILES[i]);
1586 //VM_FILES[i] = NULL;
1588 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1595 float fopen(string filename, float mode)
1598 // float(string filename, float mode) fopen = #110;
1599 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1600 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1604 char *modestring, *filename;
1606 VM_SAFEPARMCOUNT(2,VM_fopen);
1608 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1609 if (VM_FILES[filenum] == NULL)
1611 if (filenum >= MAX_VMFILES)
1613 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1614 PRVM_G_FLOAT(OFS_RETURN) = -2;
1617 mode = PRVM_G_FLOAT(OFS_PARM1);
1620 case 0: // FILE_READ
1623 case 1: // FILE_APPEND
1626 case 2: // FILE_WRITE
1630 Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1631 PRVM_G_FLOAT(OFS_RETURN) = -3;
1634 filename = PRVM_G_STRING(OFS_PARM0);
1635 // .. is parent directory on many platforms
1636 // / is parent directory on Amiga
1637 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1638 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1639 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1641 Con_Printf("VM_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
1642 PRVM_G_FLOAT(OFS_RETURN) = -4;
1645 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1646 if (VM_FILES[filenum] == NULL)
1647 PRVM_G_FLOAT(OFS_RETURN) = -1;
1649 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1656 fclose(float fhandle)
1659 //void(float fhandle) fclose = #111; // closes a file
1660 void VM_fclose(void)
1664 VM_SAFEPARMCOUNT(1,VM_fclose);
1666 filenum = PRVM_G_FLOAT(OFS_PARM0);
1667 if (filenum < 0 || filenum >= MAX_VMFILES)
1669 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1672 if (VM_FILES[filenum] == NULL)
1674 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1677 FS_Close(VM_FILES[filenum]);
1678 VM_FILES[filenum] = NULL;
1685 string fgets(float fhandle)
1688 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1692 static char string[STRINGTEMP_LENGTH];
1695 VM_SAFEPARMCOUNT(1,VM_fgets);
1697 filenum = PRVM_G_FLOAT(OFS_PARM0);
1698 if (filenum < 0 || filenum >= MAX_VMFILES)
1700 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1703 if (VM_FILES[filenum] == NULL)
1705 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1711 c = FS_Getc(VM_FILES[filenum]);
1712 if (c == '\r' || c == '\n' || c < 0)
1714 if (end < STRINGTEMP_LENGTH - 1)
1718 // remove \n following \r
1720 c = FS_Getc(VM_FILES[filenum]);
1721 if (developer.integer)
1722 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1724 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1726 PRVM_G_INT(OFS_RETURN) = 0;
1733 fputs(float fhandle, string s)
1736 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1740 char string[STRINGTEMP_LENGTH];
1743 VM_SAFEPARMCOUNT(2,VM_fputs);
1745 filenum = PRVM_G_FLOAT(OFS_PARM0);
1746 if (filenum < 0 || filenum >= MAX_VMFILES)
1748 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1751 if (VM_FILES[filenum] == NULL)
1753 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1756 VM_VarString(1, string, sizeof(string));
1757 if ((stringlength = strlen(string)))
1758 FS_Write(VM_FILES[filenum], string, stringlength);
1759 if (developer.integer)
1760 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1767 float strlen(string s)
1770 //float(string s) strlen = #114; // returns how many characters are in a string
1771 void VM_strlen(void)
1775 VM_SAFEPARMCOUNT(1,VM_strlen);
1777 s = PRVM_G_STRING(OFS_PARM0);
1779 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1781 PRVM_G_FLOAT(OFS_RETURN) = 0;
1788 string strcat(string,string,...[string])
1791 //string(string s1, string s2) strcat = #115;
1792 // concatenates two strings (for example "abc", "def" would return "abcdef")
1793 // and returns as a tempstring
1794 void VM_strcat(void)
1799 PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
1801 s = VM_GetTempString();
1802 VM_VarString(0, s, STRINGTEMP_LENGTH);
1803 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1810 string substring(string s, float start, float length)
1813 // string(string s, float start, float length) substring = #116;
1814 // returns a section of a string as a tempstring
1815 void VM_substring(void)
1817 int i, start, length;
1820 VM_SAFEPARMCOUNT(3,VM_substring);
1822 string = VM_GetTempString();
1823 s = PRVM_G_STRING(OFS_PARM0);
1824 start = PRVM_G_FLOAT(OFS_PARM1);
1825 length = PRVM_G_FLOAT(OFS_PARM2);
1828 for (i = 0;i < start && *s;i++, s++);
1829 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1832 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1839 vector stov(string s)
1842 //vector(string s) stov = #117; // returns vector value from a string
1845 char string[STRINGTEMP_LENGTH];
1847 VM_SAFEPARMCOUNT(1,VM_stov);
1849 VM_VarString(0, string, sizeof(string));
1850 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1857 string strzone(string s)
1860 //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)
1861 void VM_strzone(void)
1865 VM_SAFEPARMCOUNT(1,VM_strzone);
1867 in = PRVM_G_STRING(OFS_PARM0);
1868 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1870 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1880 //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!!!)
1881 void VM_strunzone(void)
1883 VM_SAFEPARMCOUNT(1,VM_strunzone);
1885 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1890 VM_command (used by client and menu)
1892 clientcommand(float client, string s) (for client and menu)
1895 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1896 //this function originally written by KrimZon, made shorter by LordHavoc
1897 void VM_clcommand (void)
1899 client_t *temp_client;
1902 VM_SAFEPARMCOUNT(2,VM_clcommand);
1904 i = PRVM_G_FLOAT(OFS_PARM0);
1905 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1907 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1911 temp_client = host_client;
1912 host_client = svs.clients + i;
1913 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1914 host_client = temp_client;
1922 float tokenize(string s)
1925 //float(string s) tokenize = #441;
1926 // takes apart a string into individal words (access them with argv), returns how many
1927 // this function originally written by KrimZon, made shorter by LordHavoc
1928 static char **tokens = NULL;
1929 static int max_tokens, num_tokens = 0;
1930 void VM_tokenize (void)
1935 VM_SAFEPARMCOUNT(1,VM_tokenize);
1937 str = PRVM_G_STRING(OFS_PARM0);
1942 for (i=0;i<num_tokens;i++)
1948 tokens = Z_Malloc(strlen(str) * sizeof(char *));
1949 max_tokens = strlen(str);
1951 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
1953 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
1954 strcpy(tokens[num_tokens], com_token);
1957 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
1964 string argv(float n)
1967 //string(float n) argv = #442;
1968 // returns a word from the tokenized string (returns nothing for an invalid index)
1969 // this function originally written by KrimZon, made shorter by LordHavoc
1974 VM_SAFEPARMCOUNT(1,VM_argv);
1976 token_num = PRVM_G_FLOAT(OFS_PARM0);
1977 if (token_num >= 0 && token_num < num_tokens)
1978 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
1980 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
1984 //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)
1985 void PF_setattachment (void)
1987 edict_t *e = G_EDICT(OFS_PARM0);
1988 edict_t *tagentity = G_EDICT(OFS_PARM1);
1989 char *tagname = G_STRING(OFS_PARM2);
1994 if (tagentity == NULL)
1995 tagentity = sv.edicts;
1997 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
1999 v->edict = EDICT_TO_PROG(tagentity);
2001 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2004 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2006 modelindex = (int)tagentity->v->modelindex;
2007 if (modelindex >= 0 && modelindex < MAX_MODELS)
2009 model = sv.models[modelindex];
2010 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2011 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2012 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2014 if (v->_float == 0 && model->alias.aliasnum_tags)
2015 for (i = 0;i < model->alias.aliasnum_tags;i++)
2016 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2019 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);
2022 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));
2033 void VM_isserver(void)
2035 VM_SAFEPARMCOUNT(0,VM_serverstate);
2037 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2047 void VM_clientcount(void)
2049 VM_SAFEPARMCOUNT(0,VM_clientcount);
2051 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2061 void VM_clientstate(void)
2063 VM_SAFEPARMCOUNT(0,VM_clientstate);
2065 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2068 //=============================================================================
2069 // Draw builtins (client & menu)
2075 float iscachedpic(string pic)
2078 void VM_iscachedpic(void)
2080 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2082 // drawq hasnt such a function, thus always return true
2083 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2090 string precache_pic(string pic)
2093 void VM_precache_pic(void)
2097 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2099 s = PRVM_G_STRING(OFS_PARM0);
2100 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2103 PRVM_ERROR ("VM_precache_pic: %s: NULL\n");
2105 VM_CheckEmptyString (s);
2117 void VM_freepic(void)
2121 VM_SAFEPARMCOUNT(1,VM_freepic);
2123 s = PRVM_G_STRING(OFS_PARM0);
2126 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2128 VM_CheckEmptyString (s);
2137 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2140 void VM_drawcharacter(void)
2142 float *pos,*scale,*rgb;
2145 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2147 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2150 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2151 PRVM_G_FLOAT(OFS_RETURN) = -1;
2155 pos = PRVM_G_VECTOR(OFS_PARM0);
2156 scale = PRVM_G_VECTOR(OFS_PARM2);
2157 rgb = PRVM_G_VECTOR(OFS_PARM3);
2158 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2160 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2162 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2163 PRVM_G_FLOAT(OFS_RETURN) = -2;
2167 if(pos[2] || scale[2])
2168 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")));
2170 if(!scale[0] || !scale[1])
2172 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2173 PRVM_G_FLOAT(OFS_RETURN) = -3;
2177 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2178 PRVM_G_FLOAT(OFS_RETURN) = 1;
2185 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2188 void VM_drawstring(void)
2190 float *pos,*scale,*rgb;
2193 VM_SAFEPARMCOUNT(6,VM_drawstring);
2195 string = PRVM_G_STRING(OFS_PARM1);
2198 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2199 PRVM_G_FLOAT(OFS_RETURN) = -1;
2203 VM_CheckEmptyString(string);
2205 pos = PRVM_G_VECTOR(OFS_PARM0);
2206 scale = PRVM_G_VECTOR(OFS_PARM2);
2207 rgb = PRVM_G_VECTOR(OFS_PARM3);
2208 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2210 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2212 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2213 PRVM_G_FLOAT(OFS_RETURN) = -2;
2217 if(!scale[0] || !scale[1])
2219 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2220 PRVM_G_FLOAT(OFS_RETURN) = -3;
2224 if(pos[2] || scale[2])
2225 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")));
2227 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2228 PRVM_G_FLOAT(OFS_RETURN) = 1;
2234 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2237 void VM_drawpic(void)
2240 float *size, *pos, *rgb;
2243 VM_SAFEPARMCOUNT(6,VM_drawpic);
2245 pic = PRVM_G_STRING(OFS_PARM1);
2249 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2250 PRVM_G_FLOAT(OFS_RETURN) = -1;
2254 VM_CheckEmptyString (pic);
2259 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2260 PRVM_G_FLOAT(OFS_RETURN) = -4;
2264 pos = PRVM_G_VECTOR(OFS_PARM0);
2265 size = PRVM_G_VECTOR(OFS_PARM2);
2266 rgb = PRVM_G_VECTOR(OFS_PARM3);
2267 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2269 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2271 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2272 PRVM_G_FLOAT(OFS_RETURN) = -2;
2276 if(pos[2] || size[2])
2277 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")));
2279 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2280 PRVM_G_FLOAT(OFS_RETURN) = 1;
2287 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2290 void VM_drawfill(void)
2292 float *size, *pos, *rgb;
2295 VM_SAFEPARMCOUNT(5,VM_drawfill);
2298 pos = PRVM_G_VECTOR(OFS_PARM0);
2299 size = PRVM_G_VECTOR(OFS_PARM1);
2300 rgb = PRVM_G_VECTOR(OFS_PARM2);
2301 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2303 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2305 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2306 PRVM_G_FLOAT(OFS_RETURN) = -2;
2310 if(pos[2] || size[2])
2311 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")));
2313 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2314 PRVM_G_FLOAT(OFS_RETURN) = 1;
2321 vector getmousepos()
2324 void VM_getmousepos(void)
2327 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2329 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2330 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2331 PRVM_G_VECTOR(OFS_RETURN)[0] = 0;
2334 void VM_Cmd_Init(void)
2336 // only init the stuff for the current prog
2337 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
2341 void VM_Cmd_Reset(void)
2343 Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2344 VM_Files_CloseAll();
2347 //============================================================================
2350 char *vm_sv_extensions =
2353 prvm_builtin_t vm_sv_builtins[] = {
2354 0 // to be consistent with the old vm
2357 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2359 void VM_SV_Cmd_Init(void)
2363 void VM_SV_Cmd_Reset(void)
2367 //============================================================================
2370 char *vm_cl_extensions =
2373 prvm_builtin_t vm_cl_builtins[] = {
2374 0 // to be consistent with the old vm
2377 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2379 void VM_CL_Cmd_Init(void)
2383 void VM_CL_Cmd_Reset(void)
2387 //============================================================================
2390 char *vm_m_extensions =
2397 setmousetarget(float target)
2400 void VM_M_setmousetarget(void)
2402 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2404 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2407 in_client_mouse = false;
2410 in_client_mouse = true;
2413 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2421 float getmousetarget
2424 void VM_M_getmousetarget(void)
2426 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2429 PRVM_G_FLOAT(OFS_RETURN) = 2;
2431 PRVM_G_FLOAT(OFS_RETURN) = 1;
2440 setkeydest(float dest)
2443 void VM_M_setkeydest(void)
2445 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2447 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2451 key_dest = key_game;
2455 key_dest = key_menu;
2459 // key_dest = key_message
2462 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2473 void VM_M_getkeydest(void)
2475 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2477 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2481 PRVM_G_FLOAT(OFS_RETURN) = 0;
2484 PRVM_G_FLOAT(OFS_RETURN) = 2;
2488 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2491 PRVM_G_FLOAT(OFS_RETURN) = 3;
2495 prvm_builtin_t vm_m_builtins[] = {
2496 0, // to be consistent with the old vm
2497 // common builtings (mostly)
2563 VM_getmousepos, // 66
2582 VM_WriteEntity, // 408
2608 VM_M_setmousetarget,
2612 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
2614 void VM_M_Cmd_Init(void)
2619 void VM_M_Cmd_Reset(void)