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)
93 perhaps only : Menu : WriteMsg
94 ===============================
96 WriteByte(float data, float dest, float desto)
97 WriteChar(float data, float dest, float desto)
98 WriteShort(float data, float dest, float desto)
99 WriteLong(float data, float dest, float desto)
100 WriteAngle(float data, float dest, float desto)
101 WriteCoord(float data, float dest, float desto)
102 WriteString(string data, float dest, float desto)
103 WriteEntity(entity data, float dest, float desto)
105 Client & Menu : draw functions
106 ===============================
108 float iscachedpic(string pic)
109 string precache_pic(string pic)
111 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
112 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
113 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
114 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
115 drawsetcliparea(float x, float y, float width, float height)
117 vector getimagesize(string pic)
120 ==============================================================================
124 setkeydest(float dest)
126 setmousetarget(float target)
127 float getmousetarget(void)
129 callfunction(...,string function_name)
130 writetofile(float fhandle, entity ent)
131 float isfunction(string function_name)
132 vector getresolution(float number)
135 #include "quakedef.h"
136 #include "progdefs.h"
137 #include "clprogdefs.h"
138 #include "mprogdefs.h"
140 //============================================================================
141 // nice helper macros
143 #ifndef VM_NOPARMCHECK
144 #define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !\n")
146 #define VM_SAFEPARMCOUNT(p,f)
149 #define VM_RETURN_EDICT(e) (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
151 #define VM_STRINGS_MEMPOOL vm_strings_mempool[PRVM_GetProgNr()]
153 #define e10 0,0,0,0,0,0,0,0,0,0
154 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
155 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
157 //============================================================================
160 // string zone mempool
161 mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
163 // temp string handling
164 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
165 #define VM_STRINGTEMP_BUFFERS 16
166 #define VM_STRINGTEMP_LENGTH 4096
167 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
168 static int vm_string_tempindex = 0;
171 #define MAX_QC_CVARS 128 * PRVM_MAXPROGS
172 cvar_t vm_qc_cvar[MAX_QC_CVARS];
173 int vm_currentqc_cvar;
176 #define MAX_VMFILES 256
177 #define MAX_PRVMFILES MAX_VMFILES * PRVM_MAXPROGS
178 #define VM_FILES ((qfile_t**)(vm_files + PRVM_GetProgNr() * MAX_VMFILES))
180 qfile_t *vm_files[MAX_PRVMFILES];
182 static char *VM_GetTempString(void)
185 s = vm_string_temp[vm_string_tempindex];
186 vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS;
190 void VM_CheckEmptyString (char *s)
193 PRVM_ERROR ("%s: Bad string", PRVM_NAME);
196 //============================================================================
199 void VM_VarString(int first, char *out, int outlength)
205 outend = out + outlength - 1;
206 for (i = first;i < prog->argc && out < outend;i++)
208 s = PRVM_G_STRING((OFS_PARM0+i*3));
209 while (out < outend && *s)
219 returns true if the extension is supported by the server
221 checkextension(extensionname)
225 // kind of helper function
226 static qboolean checkextension(char *name)
232 for (e = prog->extensionstring;*e;e++)
239 while (*e && *e != ' ')
241 if (e - start == len)
242 if (!strncasecmp(start, name, len))
250 void VM_checkextension (void)
252 VM_SAFEPARMCOUNT(1,VM_checkextension);
254 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
261 This is a TERMINAL error, which will kill off the entire prog.
270 char string[VM_STRINGTEMP_LENGTH];
272 VM_VarString(0, string, sizeof(string));
273 Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
276 ed = PRVM_G_EDICT(prog->self->ofs);
280 PRVM_ERROR ("%s: Program error", PRVM_NAME);
287 Dumps out self, then an error message. The program is aborted and self is
288 removed, but the level can continue.
293 void VM_objerror (void)
296 char string[VM_STRINGTEMP_LENGTH];
298 VM_VarString(0, string, sizeof(string));
299 Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
302 ed = PRVM_G_EDICT (prog->self->ofs);
308 // objerror has to display the object fields -> else call
309 PRVM_ERROR ("VM_objecterror: self not defined !\n");
314 VM_print (actually used only by client and menu)
323 char string[VM_STRINGTEMP_LENGTH];
325 VM_VarString(0, string, sizeof(string));
333 broadcast print to everyone on server
338 void VM_bprint (void)
340 char string[VM_STRINGTEMP_LENGTH];
344 Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
348 VM_VarString(0, string, sizeof(string));
349 SV_BroadcastPrintf("%s", string);
354 VM_sprint (menu & client but only if server.active == true)
356 single print to a specific client
358 sprint(float clientnum,...[string])
361 void VM_sprint (void)
365 char string[VM_STRINGTEMP_LENGTH];
367 //find client for this entity
368 clientnum = PRVM_G_FLOAT(OFS_PARM0);
369 if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
371 Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
375 client = svs.clients + clientnum;
376 if (!client->netconnection)
378 VM_VarString(1, string, sizeof(string));
379 MSG_WriteChar(&client->message,svc_print);
380 MSG_WriteString(&client->message, string);
387 single print to the screen
389 centerprint(clientent, value)
392 void VM_centerprint (void)
394 char string[VM_STRINGTEMP_LENGTH];
396 VM_VarString(0, string, sizeof(string));
397 SCR_CenterPrint(string);
404 vector normalize(vector)
407 void VM_normalize (void)
413 VM_SAFEPARMCOUNT(1,VM_normalize);
415 value1 = PRVM_G_VECTOR(OFS_PARM0);
417 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
421 newvalue[0] = newvalue[1] = newvalue[2] = 0;
425 newvalue[0] = value1[0] * new;
426 newvalue[1] = value1[1] * new;
427 newvalue[2] = value1[2] * new;
430 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
445 VM_SAFEPARMCOUNT(1,VM_vlen);
447 value1 = PRVM_G_VECTOR(OFS_PARM0);
449 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
452 PRVM_G_FLOAT(OFS_RETURN) = new;
459 float vectoyaw(vector)
462 void VM_vectoyaw (void)
467 VM_SAFEPARMCOUNT(1,VM_vectoyaw);
469 value1 = PRVM_G_VECTOR(OFS_PARM0);
471 if (value1[1] == 0 && value1[0] == 0)
475 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
480 PRVM_G_FLOAT(OFS_RETURN) = yaw;
488 vector vectoangles(vector)
491 void VM_vectoangles (void)
497 VM_SAFEPARMCOUNT(1,VM_vectoangles);
499 value1 = PRVM_G_VECTOR(OFS_PARM0);
501 if (value1[1] == 0 && value1[0] == 0)
511 // LordHavoc: optimized a bit
514 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
518 else if (value1[1] > 0)
523 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
524 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
529 PRVM_G_FLOAT(OFS_RETURN+0) = pitch;
530 PRVM_G_FLOAT(OFS_RETURN+1) = yaw;
531 PRVM_G_FLOAT(OFS_RETURN+2) = 0;
538 Returns a number from 0<= num < 1
543 void VM_random (void)
547 VM_SAFEPARMCOUNT(0,VM_random);
549 num = (rand ()&0x7fff) / ((float)0x7fff);
551 PRVM_G_FLOAT(OFS_RETURN) = num;
558 Each entity can have eight independant sound sources, like voice,
561 Channel 0 is an auto-allocate channel, the others override anything
562 already running on that entity/channel pair.
564 An attenuation of 0 will play full volume everywhere in the level.
565 Larger attenuations will drop off.
578 entity = G_EDICT(OFS_PARM0);
579 channel = G_FLOAT(OFS_PARM1);
580 sample = G_STRING(OFS_PARM2);
581 volume = G_FLOAT(OFS_PARM3) * 255;
582 attenuation = G_FLOAT(OFS_PARM4);
584 if (volume < 0 || volume > 255)
585 Host_Error ("SV_StartSound: volume = %i", volume);
587 if (attenuation < 0 || attenuation > 4)
588 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
590 if (channel < 0 || channel > 7)
591 Host_Error ("SV_StartSound: channel = %i", channel);
593 SV_StartSound (entity, channel, sample, volume, attenuation);
601 localsound(string sample)
604 void VM_localsound(void)
608 VM_SAFEPARMCOUNT(1,VM_localsound);
610 s = PRVM_G_STRING(OFS_PARM0);
614 Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
615 PRVM_G_FLOAT(OFS_RETURN) = -4;
620 PRVM_G_FLOAT(OFS_RETURN) = 1;
632 PRVM_ERROR ("%s: break statement", PRVM_NAME);
635 //============================================================================
641 Sends text over to the client's execution buffer
643 [localcmd (string) or]
647 void VM_localcmd (void)
649 VM_SAFEPARMCOUNT(1,VM_localcmd);
651 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
663 VM_SAFEPARMCOUNT(1,VM_cvar);
665 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
672 const string str_cvar (string)
675 void VM_str_cvar(void)
678 const char *cvar_string;
679 VM_SAFEPARMCOUNT(1,VM_str_cvar);
681 name = PRVM_G_STRING(OFS_PARM0);
684 PRVM_ERROR("VM_str_cvar: %s: null string\n", PRVM_NAME);
686 VM_CheckEmptyString(name);
688 out = VM_GetTempString();
690 cvar_string = Cvar_VariableString(name);
692 strcpy(out, cvar_string);
694 PRVM_G_INT(OFS_PARM0) = PRVM_SetString(out);
701 void cvar_set (string,string)
704 void VM_cvar_set (void)
706 VM_SAFEPARMCOUNT(2,VM_cvar_set);
708 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
718 void VM_dprint (void)
720 char string[VM_STRINGTEMP_LENGTH];
721 if (developer.integer)
723 VM_VarString(0, string, sizeof(string));
724 Con_Printf("%s: %s", PRVM_NAME, string);
741 VM_SAFEPARMCOUNT(1, VM_ftos);
743 v = PRVM_G_FLOAT(OFS_PARM0);
745 s = VM_GetTempString();
746 if ((float)((int)v) == v)
747 sprintf(s, "%i", (int)v);
750 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
765 VM_SAFEPARMCOUNT(1,VM_fabs);
767 v = PRVM_G_FLOAT(OFS_PARM0);
768 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
783 VM_SAFEPARMCOUNT(1,VM_vtos);
785 s = VM_GetTempString();
786 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]);
787 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
802 VM_SAFEPARMCOUNT(1, VM_etos);
804 s = VM_GetTempString();
805 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
806 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
813 float stof(...[string])
818 char string[VM_STRINGTEMP_LENGTH];
819 VM_VarString(0, string, sizeof(string));
820 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
834 prog->xfunction->builtinsprofile += 20;
835 ed = PRVM_ED_Alloc();
847 void VM_remove (void)
850 prog->xfunction->builtinsprofile += 20;
852 VM_SAFEPARMCOUNT(1, VM_remove);
854 ed = PRVM_G_EDICT(OFS_PARM0);
855 // if (ed == prog->edicts)
856 // PRVM_ERROR ("remove: tried to remove world\n");
857 // if (PRVM_NUM_FOR_EDICT(ed) <= sv.maxclients)
858 // Host_Error("remove: tried to remove a client\n");
866 entity find(entity start, .string field, string match)
877 VM_SAFEPARMCOUNT(3,VM_find);
879 e = PRVM_G_EDICTNUM(OFS_PARM0);
880 f = PRVM_G_INT(OFS_PARM1);
881 s = PRVM_G_STRING(OFS_PARM2);
885 // return reserved edict 0 (could be used for whatever the prog wants)
886 VM_RETURN_EDICT(prog->edicts);
890 for (e++ ; e < prog->num_edicts ; e++)
892 prog->xfunction->builtinsprofile++;
893 ed = PRVM_EDICT_NUM(e);
896 t = PRVM_E_STRING(ed,f);
906 VM_RETURN_EDICT(prog->edicts);
913 entity findfloat(entity start, .float field, float match)
914 entity findentity(entity start, .entity field, entity match)
917 // LordHavoc: added this for searching float, int, and entity reference fields
918 void VM_findfloat (void)
925 VM_SAFEPARMCOUNT(3,VM_findfloat);
927 e = PRVM_G_EDICTNUM(OFS_PARM0);
928 f = PRVM_G_INT(OFS_PARM1);
929 s = PRVM_G_FLOAT(OFS_PARM2);
931 for (e++ ; e < prog->num_edicts ; e++)
933 prog->xfunction->builtinsprofile++;
934 ed = PRVM_EDICT_NUM(e);
937 if (PRVM_E_FLOAT(ed,f) == s)
944 VM_RETURN_EDICT(prog->edicts);
951 entity findchain(.string field, string match)
954 int PRVM_ED_FindFieldOffset(const char *field);
955 // chained search for strings in entity fields
956 // entity(.string field, string match) findchain = #402;
957 void VM_findchain (void)
963 prvm_edict_t *ent, *chain;
965 VM_SAFEPARMCOUNT(2,VM_findchain);
967 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
968 if(!prog->flag & PRVM_FE_CHAIN)
969 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
971 chain_of = PRVM_ED_FindFieldOffset ("chain");
973 chain = prog->edicts;
975 f = PRVM_G_INT(OFS_PARM0);
976 s = PRVM_G_STRING(OFS_PARM1);
979 VM_RETURN_EDICT(prog->edicts);
983 ent = PRVM_NEXT_EDICT(prog->edicts);
984 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
986 prog->xfunction->builtinsprofile++;
989 t = PRVM_E_STRING(ent,f);
995 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
999 VM_RETURN_EDICT(chain);
1006 entity findchainfloat(.string field, float match)
1007 entity findchainentity(.string field, entity match)
1010 // LordHavoc: chained search for float, int, and entity reference fields
1011 // entity(.string field, float match) findchainfloat = #403;
1012 void VM_findchainfloat (void)
1018 prvm_edict_t *ent, *chain;
1020 VM_SAFEPARMCOUNT(2, VM_findchainfloat);
1022 if(!prog->flag & PRVM_FE_CHAIN)
1023 PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !\n", PRVM_NAME);
1025 chain_of = PRVM_ED_FindFieldOffset ("chain");
1027 chain = (prvm_edict_t *)prog->edicts;
1029 f = PRVM_G_INT(OFS_PARM0);
1030 s = PRVM_G_FLOAT(OFS_PARM1);
1032 ent = PRVM_NEXT_EDICT(prog->edicts);
1033 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1035 prog->xfunction->builtinsprofile++;
1038 if (E_FLOAT(ent,f) != s)
1041 PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
1045 VM_RETURN_EDICT(chain);
1052 string precache_file(string)
1055 void VM_precache_file (void)
1056 { // precache_file is only used to copy files with qcc, it does nothing
1057 VM_SAFEPARMCOUNT(1,VM_precache_file);
1059 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1066 used instead of the other VM_precache_* functions in the builtin list
1070 void VM_precache_error (void)
1072 PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
1079 string precache_sound (string sample)
1082 void VM_precache_sound (void)
1086 VM_SAFEPARMCOUNT(1, VM_precache_sound);
1088 s = PRVM_G_STRING(OFS_PARM0);
1089 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1090 VM_CheckEmptyString (s);
1094 Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
1098 if(!S_PrecacheSound(s,true))
1099 Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
1109 void VM_coredump (void)
1111 VM_SAFEPARMCOUNT(0,VM_coredump);
1113 Cbuf_AddText("prvm_edicts ");
1114 Cbuf_AddText(PRVM_NAME);
1125 void PRVM_StackTrace(void);
1126 void VM_stackdump (void)
1128 VM_SAFEPARMCOUNT(0, VM_stackdump);
1143 VM_SAFEPARMCOUNT(0, VM_crash);
1145 PRVM_ERROR("Crash called by %s\n",PRVM_NAME);
1155 void VM_traceon (void)
1157 VM_SAFEPARMCOUNT(0,VM_traceon);
1169 void VM_traceoff (void)
1171 VM_SAFEPARMCOUNT(0,VM_traceoff);
1173 prog->trace = false;
1183 void VM_eprint (void)
1185 VM_SAFEPARMCOUNT(1,VM_eprint);
1187 PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1201 VM_SAFEPARMCOUNT(1,VM_rint);
1203 f = PRVM_G_FLOAT(OFS_PARM0);
1205 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1207 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1217 void VM_floor (void)
1219 VM_SAFEPARMCOUNT(1,VM_floor);
1221 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1233 VM_SAFEPARMCOUNT(1,VM_ceil);
1235 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1243 entity nextent(entity)
1246 void VM_nextent (void)
1251 i = PRVM_G_EDICTNUM(OFS_PARM0);
1254 prog->xfunction->builtinsprofile++;
1256 if (i == prog->num_edicts)
1258 VM_RETURN_EDICT(prog->edicts);
1261 ent = PRVM_EDICT_NUM(i);
1264 VM_RETURN_EDICT(ent);
1271 ===============================================================================
1274 used only for client and menu
1275 severs uses VM_SV_...
1277 Write*(* data, float type, float to)
1279 ===============================================================================
1282 #define MSG_BROADCAST 0 // unreliable to all
1283 #define MSG_ONE 1 // reliable to one (msg_entity)
1284 #define MSG_ALL 2 // reliable to all
1285 #define MSG_INIT 3 // write to the init string
1287 sizebuf_t *VM_WriteDest (void)
1293 PRVM_ERROR("VM_WriteDest: game is not server (%s)\n", PRVM_NAME);
1295 dest = G_FLOAT(OFS_PARM1);
1299 return &sv.datagram;
1302 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
1303 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active)
1304 PRVM_ERROR("VM_clientcommand: %s: invalid client !\n", PRVM_NAME);
1306 return &svs.clients[destclient].message;
1309 return &sv.reliable_datagram;
1315 PRVM_ERROR ("WriteDest: bad destination");
1322 void VM_WriteByte (void)
1324 MSG_WriteByte (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1327 void VM_WriteChar (void)
1329 MSG_WriteChar (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1332 void VM_WriteShort (void)
1334 MSG_WriteShort (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1337 void VM_WriteLong (void)
1339 MSG_WriteLong (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1342 void VM_WriteAngle (void)
1344 MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1347 void VM_WriteCoord (void)
1349 MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
1352 void VM_WriteString (void)
1354 MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
1357 void VM_WriteEntity (void)
1359 MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
1362 //=============================================================================
1369 changelevel(string map)
1372 void VM_changelevel (void)
1376 VM_SAFEPARMCOUNT(1, VM_changelevel);
1380 Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
1384 // make sure we don't issue two changelevels
1385 if (svs.changelevel_issued)
1387 svs.changelevel_issued = true;
1389 s = G_STRING(OFS_PARM0);
1390 Cbuf_AddText (va("changelevel %s\n",s));
1402 VM_SAFEPARMCOUNT(1,VM_sin);
1403 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1414 VM_SAFEPARMCOUNT(1,VM_cos);
1415 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1427 VM_SAFEPARMCOUNT(1,VM_sqrt);
1428 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1435 Returns a vector of length < 1 and > 0
1440 void VM_randomvec (void)
1445 VM_SAFEPARMCOUNT(0, VM_randomvec);
1450 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1451 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1452 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1454 while (DotProduct(temp, temp) >= 1);
1455 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1458 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1459 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1460 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1461 // length returned always > 0
1462 length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
1463 VectorScale(temp,length, temp);*/
1464 //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
1467 //=============================================================================
1473 float registercvar (string name, string value)
1476 void VM_registercvar (void)
1481 VM_SAFEPARMCOUNT(2,VM_registercvar);
1483 name = PRVM_G_STRING(OFS_PARM0);
1484 value = PRVM_G_STRING(OFS_PARM1);
1485 PRVM_G_FLOAT(OFS_RETURN) = 0;
1486 // first check to see if it has already been defined
1487 if (Cvar_FindVar (name))
1490 // check for overlap with a command
1491 if (Cmd_Exists (name))
1493 Con_Printf ("VM_registercvar: %s is a command\n", name);
1497 if (vm_currentqc_cvar >= MAX_QC_CVARS)
1498 PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1500 // copy the name and value
1501 variable = &vm_qc_cvar[vm_currentqc_cvar++];
1502 variable->name = Z_Malloc (strlen(name)+1);
1503 strcpy (variable->name, name);
1504 variable->string = Z_Malloc (strlen(value)+1);
1505 strcpy (variable->string, value);
1506 variable->value = atof (value);
1508 Cvar_RegisterVariable(variable);
1509 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1516 returns the minimum of two supplied floats
1518 float min(float a, float b, ...[float])
1523 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1524 if (prog->argc == 2)
1525 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1526 else if (prog->argc >= 3)
1529 float f = PRVM_G_FLOAT(OFS_PARM0);
1530 for (i = 1;i < prog->argc;i++)
1531 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
1532 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1533 PRVM_G_FLOAT(OFS_RETURN) = f;
1536 PRVM_ERROR("VM_min: %s must supply at least 2 floats\n", PRVM_NAME);
1543 returns the maximum of two supplied floats
1545 float max(float a, float b, ...[float])
1550 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1551 if (prog->argc == 2)
1552 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1553 else if (prog->argc >= 3)
1556 float f = PRVM_G_FLOAT(OFS_PARM0);
1557 for (i = 1;i < prog->argc;i++)
1558 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
1559 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
1560 G_FLOAT(OFS_RETURN) = f;
1563 PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
1570 returns number bounded by supplied range
1572 float bound(float min, float value, float max)
1575 void VM_bound (void)
1577 VM_SAFEPARMCOUNT(3,VM_bound);
1578 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1585 returns a raised to power b
1587 float pow(float a, float b)
1592 VM_SAFEPARMCOUNT(2,VM_pow);
1593 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
1600 copies data from one entity to another
1602 copyentity(entity src, entity dst)
1605 void VM_copyentity (void)
1607 prvm_edict_t *in, *out;
1608 VM_SAFEPARMCOUNT(2,VM_copyentity);
1609 in = PRVM_G_EDICT(OFS_PARM0);
1610 out = PRVM_G_EDICT(OFS_PARM1);
1611 memcpy(out->v, in->v, prog->progs->entityfields * 4);
1618 sets the color of a client and broadcasts the update to all connected clients
1620 setcolor(clientent, value)
1623 /*void PF_setcolor (void)
1629 entnum = G_EDICTNUM(OFS_PARM0);
1630 i = G_FLOAT(OFS_PARM1);
1632 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1634 Con_Printf ("tried to setcolor a non-client\n");
1638 client = svs.clients + entnum-1;
1639 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1642 client->old_colors = i;
1643 client->edict->v->team = (i & 15) + 1;
1645 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1646 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
1647 MSG_WriteByte (&sv.reliable_datagram, i);
1650 void VM_Files_Init(void)
1652 memset(VM_FILES, 0, sizeof(qfile_t*[MAX_VMFILES]));
1655 void VM_Files_CloseAll(void)
1658 for (i = 0;i < MAX_VMFILES;i++)
1661 FS_Close(VM_FILES[i]);
1662 //VM_FILES[i] = NULL;
1664 memset(VM_FILES,0,sizeof(qfile_t*[MAX_VMFILES])); // this should be faster (is it ?)
1671 float fopen(string filename, float mode)
1674 // float(string filename, float mode) fopen = #110;
1675 // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
1676 // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
1680 char *modestring, *filename;
1682 VM_SAFEPARMCOUNT(2,VM_fopen);
1684 for (filenum = 0;filenum < MAX_VMFILES;filenum++)
1685 if (VM_FILES[filenum] == NULL)
1687 if (filenum >= MAX_VMFILES)
1689 Con_Printf("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, MAX_VMFILES);
1690 PRVM_G_FLOAT(OFS_RETURN) = -2;
1693 mode = PRVM_G_FLOAT(OFS_PARM1);
1696 case 0: // FILE_READ
1699 case 1: // FILE_APPEND
1702 case 2: // FILE_WRITE
1706 Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
1707 PRVM_G_FLOAT(OFS_RETURN) = -3;
1710 filename = PRVM_G_STRING(OFS_PARM0);
1711 // .. is parent directory on many platforms
1712 // / is parent directory on Amiga
1713 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
1714 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
1715 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
1717 Con_Printf("VM_fopen: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
1718 PRVM_G_FLOAT(OFS_RETURN) = -4;
1721 VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
1722 if (VM_FILES[filenum] == NULL)
1723 PRVM_G_FLOAT(OFS_RETURN) = -1;
1725 PRVM_G_FLOAT(OFS_RETURN) = filenum;
1732 fclose(float fhandle)
1735 //void(float fhandle) fclose = #111; // closes a file
1736 void VM_fclose(void)
1740 VM_SAFEPARMCOUNT(1,VM_fclose);
1742 filenum = PRVM_G_FLOAT(OFS_PARM0);
1743 if (filenum < 0 || filenum >= MAX_VMFILES)
1745 Con_Printf("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1748 if (VM_FILES[filenum] == NULL)
1750 Con_Printf("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1753 FS_Close(VM_FILES[filenum]);
1754 VM_FILES[filenum] = NULL;
1761 string fgets(float fhandle)
1764 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
1768 static char string[VM_STRINGTEMP_LENGTH];
1771 VM_SAFEPARMCOUNT(1,VM_fgets);
1773 filenum = PRVM_G_FLOAT(OFS_PARM0);
1774 if (filenum < 0 || filenum >= MAX_VMFILES)
1776 Con_Printf("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1779 if (VM_FILES[filenum] == NULL)
1781 Con_Printf("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1787 c = FS_Getc(VM_FILES[filenum]);
1788 if (c == '\r' || c == '\n' || c < 0)
1790 if (end < VM_STRINGTEMP_LENGTH - 1)
1794 // remove \n following \r
1796 c = FS_Getc(VM_FILES[filenum]);
1797 if (developer.integer)
1798 Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
1800 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1802 PRVM_G_INT(OFS_RETURN) = 0;
1809 fputs(float fhandle, string s)
1812 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
1816 char string[VM_STRINGTEMP_LENGTH];
1819 VM_SAFEPARMCOUNT(2,VM_fputs);
1821 filenum = PRVM_G_FLOAT(OFS_PARM0);
1822 if (filenum < 0 || filenum >= MAX_VMFILES)
1824 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
1827 if (VM_FILES[filenum] == NULL)
1829 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
1832 VM_VarString(1, string, sizeof(string));
1833 if ((stringlength = strlen(string)))
1834 FS_Write(VM_FILES[filenum], string, stringlength);
1835 if (developer.integer)
1836 Con_Printf("fputs: %s: %s\n", PRVM_NAME, string);
1843 float strlen(string s)
1846 //float(string s) strlen = #114; // returns how many characters are in a string
1847 void VM_strlen(void)
1851 VM_SAFEPARMCOUNT(1,VM_strlen);
1853 s = PRVM_G_STRING(OFS_PARM0);
1855 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
1857 PRVM_G_FLOAT(OFS_RETURN) = 0;
1864 string strcat(string,string,...[string])
1867 //string(string s1, string s2) strcat = #115;
1868 // concatenates two strings (for example "abc", "def" would return "abcdef")
1869 // and returns as a tempstring
1870 void VM_strcat(void)
1875 PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
1877 s = VM_GetTempString();
1878 VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
1879 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
1886 string substring(string s, float start, float length)
1889 // string(string s, float start, float length) substring = #116;
1890 // returns a section of a string as a tempstring
1891 void VM_substring(void)
1893 int i, start, length;
1896 VM_SAFEPARMCOUNT(3,VM_substring);
1898 string = VM_GetTempString();
1899 s = PRVM_G_STRING(OFS_PARM0);
1900 start = PRVM_G_FLOAT(OFS_PARM1);
1901 length = PRVM_G_FLOAT(OFS_PARM2);
1904 for (i = 0;i < start && *s;i++, s++);
1905 for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
1908 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
1915 vector stov(string s)
1918 //vector(string s) stov = #117; // returns vector value from a string
1921 char string[VM_STRINGTEMP_LENGTH];
1923 VM_SAFEPARMCOUNT(1,VM_stov);
1925 VM_VarString(0, string, sizeof(string));
1926 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
1933 string strzone(string s)
1936 //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)
1937 void VM_strzone(void)
1941 VM_SAFEPARMCOUNT(1,VM_strzone);
1943 in = PRVM_G_STRING(OFS_PARM0);
1944 out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
1946 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
1956 //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!!!)
1957 void VM_strunzone(void)
1959 VM_SAFEPARMCOUNT(1,VM_strunzone);
1961 Mem_Free(PRVM_G_STRING(OFS_PARM0));
1966 VM_command (used by client and menu)
1968 clientcommand(float client, string s) (for client and menu)
1971 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1972 //this function originally written by KrimZon, made shorter by LordHavoc
1973 void VM_clcommand (void)
1975 client_t *temp_client;
1978 VM_SAFEPARMCOUNT(2,VM_clcommand);
1980 i = PRVM_G_FLOAT(OFS_PARM0);
1981 if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1983 Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
1987 temp_client = host_client;
1988 host_client = svs.clients + i;
1989 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1990 host_client = temp_client;
1998 float tokenize(string s)
2001 //float(string s) tokenize = #441;
2002 // takes apart a string into individal words (access them with argv), returns how many
2003 // this function originally written by KrimZon, made shorter by LordHavoc
2004 static char **tokens = NULL;
2005 static int max_tokens, num_tokens = 0;
2006 void VM_tokenize (void)
2011 VM_SAFEPARMCOUNT(1,VM_tokenize);
2013 str = PRVM_G_STRING(OFS_PARM0);
2018 for (i=0;i<num_tokens;i++)
2024 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2025 max_tokens = strlen(str);
2027 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2029 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2030 strcpy(tokens[num_tokens], com_token);
2033 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
2040 string argv(float n)
2043 //string(float n) argv = #442;
2044 // returns a word from the tokenized string (returns nothing for an invalid index)
2045 // this function originally written by KrimZon, made shorter by LordHavoc
2050 VM_SAFEPARMCOUNT(1,VM_argv);
2052 token_num = PRVM_G_FLOAT(OFS_PARM0);
2053 if (token_num >= 0 && token_num < num_tokens)
2054 PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
2056 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2060 //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)
2061 void PF_setattachment (void)
2063 edict_t *e = G_EDICT(OFS_PARM0);
2064 edict_t *tagentity = G_EDICT(OFS_PARM1);
2065 char *tagname = G_STRING(OFS_PARM2);
2070 if (tagentity == NULL)
2071 tagentity = sv.edicts;
2073 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
2075 v->edict = EDICT_TO_PROG(tagentity);
2077 v = GETEDICTFIELDVALUE(e, eval_tag_index);
2080 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
2082 modelindex = (int)tagentity->v->modelindex;
2083 if (modelindex >= 0 && modelindex < MAX_MODELS)
2085 model = sv.models[modelindex];
2086 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
2087 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
2088 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
2090 if (v->_float == 0 && model->alias.aliasnum_tags)
2091 for (i = 0;i < model->alias.aliasnum_tags;i++)
2092 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
2095 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);
2098 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));
2109 void VM_isserver(void)
2111 VM_SAFEPARMCOUNT(0,VM_serverstate);
2113 PRVM_G_FLOAT(OFS_RETURN) = sv.active;
2123 void VM_clientcount(void)
2125 VM_SAFEPARMCOUNT(0,VM_clientcount);
2127 PRVM_G_FLOAT(OFS_RETURN) = svs.maxclients;
2137 void VM_clientstate(void)
2139 VM_SAFEPARMCOUNT(0,VM_clientstate);
2141 PRVM_G_FLOAT(OFS_RETURN) = cls.state;
2148 float getostype(void)
2150 */ // not used at the moment -> not included in the common list
2151 void VM_getostype(void)
2153 VM_SAFEPARMCOUNT(0,VM_getostype);
2158 OS_MAC - not supported
2162 PRVM_G_FLOAT(OFS_RETURN) = 0;
2164 PRVM_G_FLOAT(OFS_RETURN) = 2;
2166 PRVM_G_FLOAT(OFS_RETURN) = 1;
2174 vector getmousepos()
2177 void VM_getmousepos(void)
2180 VM_SAFEPARMCOUNT(0,VM_getmousepos);
2182 PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
2183 PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
2184 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2194 void VM_gettime(void)
2196 VM_SAFEPARMCOUNT(0,VM_gettime);
2198 PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time;
2205 loadfromdata(string data)
2208 void VM_loadfromdata(void)
2210 VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
2212 PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
2219 loadfromfile(string file)
2222 void VM_loadfromfile(void)
2227 VM_SAFEPARMCOUNT(1,VM_loadfromfile);
2229 filename = PRVM_G_STRING(OFS_PARM0);
2230 // .. is parent directory on many platforms
2231 // / is parent directory on Amiga
2232 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2233 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2234 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2236 Con_Printf("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
2237 PRVM_G_FLOAT(OFS_RETURN) = -4;
2241 // not conform with VM_fopen
2242 data = FS_LoadFile(filename, false);
2244 PRVM_G_FLOAT(OFS_RETURN) = -1;
2246 PRVM_ED_LoadFromFile(data);
2257 float mod(float val, float m)
2260 void VM_modulo(void)
2263 VM_SAFEPARMCOUNT(2,VM_module);
2265 val = (int) PRVM_G_FLOAT(OFS_PARM0);
2266 m = (int) PRVM_G_FLOAT(OFS_PARM1);
2268 PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
2271 //=============================================================================
2272 // Draw builtins (client & menu)
2278 float iscachedpic(string pic)
2281 void VM_iscachedpic(void)
2283 VM_SAFEPARMCOUNT(1,VM_iscachedpic);
2285 // drawq hasnt such a function, thus always return true
2286 PRVM_G_FLOAT(OFS_RETURN) = TRUE;
2293 string precache_pic(string pic)
2296 void VM_precache_pic(void)
2300 VM_SAFEPARMCOUNT(1, VM_precache_pic);
2302 s = PRVM_G_STRING(OFS_PARM0);
2303 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
2306 PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
2308 VM_CheckEmptyString (s);
2310 if(!Draw_CachePic(s))
2311 PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
2321 void VM_freepic(void)
2325 VM_SAFEPARMCOUNT(1,VM_freepic);
2327 s = PRVM_G_STRING(OFS_PARM0);
2330 PRVM_ERROR ("VM_freepic: %s: NULL\n");
2332 VM_CheckEmptyString (s);
2341 float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
2344 void VM_drawcharacter(void)
2346 float *pos,*scale,*rgb;
2349 VM_SAFEPARMCOUNT(6,VM_drawcharacter);
2351 character = (char) PRVM_G_FLOAT(OFS_PARM1);
2354 Con_Printf("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
2355 PRVM_G_FLOAT(OFS_RETURN) = -1;
2359 pos = PRVM_G_VECTOR(OFS_PARM0);
2360 scale = PRVM_G_VECTOR(OFS_PARM2);
2361 rgb = PRVM_G_VECTOR(OFS_PARM3);
2362 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2364 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2366 Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2367 PRVM_G_FLOAT(OFS_RETURN) = -2;
2371 if(pos[2] || scale[2])
2372 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")));
2374 if(!scale[0] || !scale[1])
2376 Con_Printf("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2377 PRVM_G_FLOAT(OFS_RETURN) = -3;
2381 DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2382 PRVM_G_FLOAT(OFS_RETURN) = 1;
2389 float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
2392 void VM_drawstring(void)
2394 float *pos,*scale,*rgb;
2397 VM_SAFEPARMCOUNT(6,VM_drawstring);
2399 string = PRVM_G_STRING(OFS_PARM1);
2402 Con_Printf("VM_drawstring: %s passed null string !\n",PRVM_NAME);
2403 PRVM_G_FLOAT(OFS_RETURN) = -1;
2407 VM_CheckEmptyString(string);
2409 pos = PRVM_G_VECTOR(OFS_PARM0);
2410 scale = PRVM_G_VECTOR(OFS_PARM2);
2411 rgb = PRVM_G_VECTOR(OFS_PARM3);
2412 flag = (int)PRVM_G_FLOAT(OFS_PARM5);
2414 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2416 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2417 PRVM_G_FLOAT(OFS_RETURN) = -2;
2421 if(!scale[0] || !scale[1])
2423 Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
2424 PRVM_G_FLOAT(OFS_RETURN) = -3;
2428 if(pos[2] || scale[2])
2429 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")));
2431 DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2432 PRVM_G_FLOAT(OFS_RETURN) = 1;
2438 float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
2441 void VM_drawpic(void)
2444 float *size, *pos, *rgb;
2447 VM_SAFEPARMCOUNT(6,VM_drawpic);
2449 pic = PRVM_G_STRING(OFS_PARM1);
2453 Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
2454 PRVM_G_FLOAT(OFS_RETURN) = -1;
2458 VM_CheckEmptyString (pic);
2460 // is pic cached ? no function yet for that
2463 Con_Printf("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, pic);
2464 PRVM_G_FLOAT(OFS_RETURN) = -4;
2468 pos = PRVM_G_VECTOR(OFS_PARM0);
2469 size = PRVM_G_VECTOR(OFS_PARM2);
2470 rgb = PRVM_G_VECTOR(OFS_PARM3);
2471 flag = (int) PRVM_G_FLOAT(OFS_PARM5);
2473 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2475 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2476 PRVM_G_FLOAT(OFS_RETURN) = -2;
2480 if(pos[2] || size[2])
2481 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")));
2483 DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
2484 PRVM_G_FLOAT(OFS_RETURN) = 1;
2491 float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
2494 void VM_drawfill(void)
2496 float *size, *pos, *rgb;
2499 VM_SAFEPARMCOUNT(5,VM_drawfill);
2502 pos = PRVM_G_VECTOR(OFS_PARM0);
2503 size = PRVM_G_VECTOR(OFS_PARM1);
2504 rgb = PRVM_G_VECTOR(OFS_PARM2);
2505 flag = (int) PRVM_G_FLOAT(OFS_PARM4);
2507 if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
2509 Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
2510 PRVM_G_FLOAT(OFS_RETURN) = -2;
2514 if(pos[2] || size[2])
2515 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")));
2517 DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
2518 PRVM_G_FLOAT(OFS_RETURN) = 1;
2525 drawsetcliparea(float x, float y, float width, float height)
2528 void VM_drawsetcliparea(void)
2531 VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
2533 x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
2534 y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
2535 w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth - x));
2536 h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y));
2538 DrawQ_SetClipArea(x,y,w,h);
2543 VM_drawresetcliparea
2548 void VM_drawresetcliparea(void)
2550 VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
2552 DrawQ_ResetClipArea();
2559 vector getimagesize(string pic)
2562 void VM_getimagesize(void)
2567 VM_SAFEPARMCOUNT(1,VM_getimagesize);
2569 p = PRVM_G_STRING(OFS_PARM0);
2572 PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
2574 VM_CheckEmptyString (p);
2576 pic = Draw_CachePic (p);
2578 PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
2579 PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
2580 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2583 void VM_Cmd_Init(void)
2585 // only init the stuff for the current prog
2586 VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
2590 void VM_Cmd_Reset(void)
2592 //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
2593 Mem_FreePool(&VM_STRINGS_MEMPOOL);
2594 VM_Files_CloseAll();
2597 //============================================================================
2600 char *vm_sv_extensions =
2603 prvm_builtin_t vm_sv_builtins[] = {
2604 0 // to be consistent with the old vm
2607 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2609 void VM_SV_Cmd_Init(void)
2613 void VM_SV_Cmd_Reset(void)
2617 //============================================================================
2620 char *vm_cl_extensions =
2623 prvm_builtin_t vm_cl_builtins[] = {
2624 0 // to be consistent with the old vm
2627 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2629 void VM_CL_Cmd_Init(void)
2633 void VM_CL_Cmd_Reset(void)
2637 //============================================================================
2640 char *vm_m_extensions =
2647 setmousetarget(float target)
2650 void VM_M_setmousetarget(void)
2652 VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
2654 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2657 in_client_mouse = false;
2660 in_client_mouse = true;
2663 PRVM_ERROR("VM_M_setmousetarget: wrong destination %i !\n",PRVM_G_FLOAT(OFS_PARM0));
2671 float getmousetarget
2674 void VM_M_getmousetarget(void)
2676 VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
2679 PRVM_G_FLOAT(OFS_RETURN) = 2;
2681 PRVM_G_FLOAT(OFS_RETURN) = 1;
2690 setkeydest(float dest)
2693 void VM_M_setkeydest(void)
2695 VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
2697 switch((int)PRVM_G_FLOAT(OFS_PARM0))
2701 key_dest = key_game;
2705 key_dest = key_menu;
2709 // key_dest = key_message
2712 PRVM_ERROR("VM_M_setkeydest: wrong destination %i !\n",prog->globals[OFS_PARM0]);
2723 void VM_M_getkeydest(void)
2725 VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
2727 // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
2731 PRVM_G_FLOAT(OFS_RETURN) = 0;
2734 PRVM_G_FLOAT(OFS_RETURN) = 2;
2738 // PRVM_G_FLOAT(OFS_RETURN) = 1;
2741 PRVM_G_FLOAT(OFS_RETURN) = 3;
2749 callfunction(...,string function_name)
2752 mfunction_t *PRVM_ED_FindFunction (const char *name);
2753 void VM_M_callfunction(void)
2759 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
2761 s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
2764 PRVM_ERROR("VM_M_callfunction: null string !\n");
2766 VM_CheckEmptyString(s);
2768 func = PRVM_ED_FindFunction(s);
2771 PRVM_ERROR("VM_M_callfunciton: function %s not found !\n", s);
2772 else if (func->first_statement < 0)
2774 // negative statements are built in functions
2775 int builtinnumber = -func->first_statement;
2776 prog->xfunction->builtinsprofile++;
2777 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
2778 prog->builtins[builtinnumber]();
2780 PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
2785 PRVM_ExecuteProgram(func - prog->functions,"");
2794 float isfunction(string function_name)
2797 mfunction_t *PRVM_ED_FindFunction (const char *name);
2798 void VM_M_isfunction(void)
2803 VM_SAFEPARMCOUNT(1, VM_M_isfunction);
2805 s = PRVM_G_STRING(OFS_PARM0);
2808 PRVM_ERROR("VM_M_isfunction: null string !\n");
2810 VM_CheckEmptyString(s);
2812 func = PRVM_ED_FindFunction(s);
2815 PRVM_G_FLOAT(OFS_RETURN) = false;
2817 PRVM_G_FLOAT(OFS_RETURN) = true;
2824 writetofile(float fhandle, entity ent)
2827 void VM_M_writetofile(void)
2832 VM_SAFEPARMCOUNT(2, VM_M_writetofile);
2834 filenum = PRVM_G_FLOAT(OFS_PARM0);
2835 if (filenum < 0 || filenum >= MAX_VMFILES)
2837 Con_Printf("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
2840 if (VM_FILES[filenum] == NULL)
2842 Con_Printf("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
2846 ent = PRVM_G_EDICT(OFS_PARM1);
2849 Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
2853 PRVM_ED_Write (VM_FILES[filenum], ent);
2860 vector getresolution(float number)
2863 extern unsigned short video_resolutions[][2];
2864 void VM_M_getresolution(void)
2867 VM_SAFEPARMCOUNT(1, VM_getresolution);
2869 nr = PRVM_G_FLOAT(OFS_PARM0);
2872 PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
2873 PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
2874 PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
2877 prvm_builtin_t vm_m_builtins[] = {
2878 0, // to be consistent with the old vm
2879 // common builtings (mostly)
2967 VM_WriteEntity, // 408
2983 VM_drawresetcliparea,
2984 VM_getimagesize,// 460
2993 VM_M_setmousetarget,
2994 VM_M_getmousetarget,
2998 VM_M_getresolution // 608
3001 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
3003 void VM_M_Cmd_Init(void)
3008 void VM_M_Cmd_Reset(void)