251bbb831309af35a41ddc2e926c04e24f442faf
[xonotic/darkplaces.git] / mvm_cmds.c
1 #include "prvm_cmds.h"
2
3 //============================================================================
4 // Menu
5
6 char *vm_m_extensions =
7 "DP_CINEMATIC_DPV "
8 "DP_MENU_EXTRESPONSEPACKET "
9 "DP_QC_ASINACOSATANATAN2TAN "
10 "DP_QC_STRINGCOLORFUNCTIONS "
11 "DP_QC_UNLIMITEDTEMPSTRINGS";
12
13 /*
14 =========
15 VM_M_precache_file
16
17 string  precache_file(string)
18 =========
19 */
20 void VM_M_precache_file (void)
21 {       // precache_file is only used to copy files with qcc, it does nothing
22         VM_SAFEPARMCOUNT(1,VM_precache_file);
23
24         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
25 }
26
27 /*
28 =========
29 VM_M_preache_error
30
31 used instead of the other VM_precache_* functions in the builtin list
32 =========
33 */
34
35 void VM_M_precache_error (void)
36 {
37         PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions");
38 }
39
40 /*
41 =========
42 VM_M_precache_sound
43
44 string  precache_sound (string sample)
45 =========
46 */
47 void VM_M_precache_sound (void)
48 {
49         const char      *s;
50
51         VM_SAFEPARMCOUNT(1, VM_precache_sound);
52
53         s = PRVM_G_STRING(OFS_PARM0);
54         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
55         VM_CheckEmptyString (s);
56
57         if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
58         {
59                 VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
60                 return;
61         }
62 }
63
64 /*
65 =========
66 VM_M_setmousetarget
67
68 setmousetarget(float target)
69 =========
70 */
71 void VM_M_setmousetarget(void)
72 {
73         VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
74
75         switch((int)PRVM_G_FLOAT(OFS_PARM0))
76         {
77         case 1:
78                 in_client_mouse = false;
79                 break;
80         case 2:
81                 in_client_mouse = true;
82                 break;
83         default:
84                 PRVM_ERROR("VM_M_setmousetarget: wrong destination %f !",PRVM_G_FLOAT(OFS_PARM0));
85         }
86 }
87
88 /*
89 =========
90 VM_M_getmousetarget
91
92 float   getmousetarget
93 =========
94 */
95 void VM_M_getmousetarget(void)
96 {
97         VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
98
99         if(in_client_mouse)
100                 PRVM_G_FLOAT(OFS_RETURN) = 2;
101         else
102                 PRVM_G_FLOAT(OFS_RETURN) = 1;
103 }
104
105
106
107 /*
108 =========
109 VM_M_setkeydest
110
111 setkeydest(float dest)
112 =========
113 */
114 void VM_M_setkeydest(void)
115 {
116         VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
117
118         switch((int)PRVM_G_FLOAT(OFS_PARM0))
119         {
120         case 0:
121                 // key_game
122                 key_dest = key_game;
123                 break;
124         case 2:
125                 // key_menu
126                 key_dest = key_menu;
127                 break;
128         case 1:
129                 // key_message
130                 // key_dest = key_message
131                 // break;
132         default:
133                 PRVM_ERROR("VM_M_setkeydest: wrong destination %f !", PRVM_G_FLOAT(OFS_PARM0));
134         }
135 }
136
137 /*
138 =========
139 VM_M_getkeydest
140
141 float   getkeydest
142 =========
143 */
144 void VM_M_getkeydest(void)
145 {
146         VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
147
148         // key_game = 0, key_message = 1, key_menu = 2, unknown = 3
149         switch(key_dest)
150         {
151         case key_game:
152                 PRVM_G_FLOAT(OFS_RETURN) = 0;
153                 break;
154         case key_menu:
155                 PRVM_G_FLOAT(OFS_RETURN) = 2;
156                 break;
157         case key_message:
158                 // not supported
159                 // PRVM_G_FLOAT(OFS_RETURN) = 1;
160                 // break;
161         default:
162                 PRVM_G_FLOAT(OFS_RETURN) = 3;
163         }
164 }
165
166 /*
167 =========
168 VM_M_callfunction
169
170         callfunction(...,string function_name)
171 Extension: pass
172 =========
173 */
174 mfunction_t *PRVM_ED_FindFunction (const char *name);
175 void VM_M_callfunction(void)
176 {
177         mfunction_t *func;
178         const char *s;
179
180         if(prog->argc == 0)
181                 PRVM_ERROR("VM_M_callfunction: 1 parameter is required !");
182
183         s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1));
184
185         VM_CheckEmptyString(s);
186
187         func = PRVM_ED_FindFunction(s);
188
189         if(!func)
190                 PRVM_ERROR("VM_M_callfunciton: function %s not found !", s);
191         else if (func->first_statement < 0)
192         {
193                 // negative statements are built in functions
194                 int builtinnumber = -func->first_statement;
195                 prog->xfunction->builtinsprofile++;
196                 if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
197                         prog->builtins[builtinnumber]();
198                 else
199                         PRVM_ERROR("No such builtin #%i in %s", builtinnumber, PRVM_NAME);
200         }
201         else if(func > 0)
202         {
203                 prog->argc--;
204                 PRVM_ExecuteProgram(func - prog->functions,"");
205                 prog->argc++;
206         }
207 }
208
209 /*
210 =========
211 VM_M_isfunction
212
213 float   isfunction(string function_name)
214 =========
215 */
216 mfunction_t *PRVM_ED_FindFunction (const char *name);
217 void VM_M_isfunction(void)
218 {
219         mfunction_t *func;
220         const char *s;
221
222         VM_SAFEPARMCOUNT(1, VM_M_isfunction);
223
224         s = PRVM_G_STRING(OFS_PARM0);
225
226         VM_CheckEmptyString(s);
227
228         func = PRVM_ED_FindFunction(s);
229
230         if(!func)
231                 PRVM_G_FLOAT(OFS_RETURN) = false;
232         else
233                 PRVM_G_FLOAT(OFS_RETURN) = true;
234 }
235
236 /*
237 =========
238 VM_M_writetofile
239
240         writetofile(float fhandle, entity ent)
241 =========
242 */
243 void VM_M_writetofile(void)
244 {
245         prvm_edict_t * ent;
246         qfile_t *file;
247
248         VM_SAFEPARMCOUNT(2, VM_M_writetofile);
249
250         file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) );
251         if( !file )
252         {
253                 VM_Warning("VM_M_writetofile: invalid or closed file handle\n");
254                 return;
255         }
256
257         ent = PRVM_G_EDICT(OFS_PARM1);
258         if(ent->priv.required->free)
259         {
260                 VM_Warning("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
261                 return;
262         }
263
264         PRVM_ED_Write (file, ent);
265 }
266
267 /*
268 =========
269 VM_M_getresolution
270
271 vector  getresolution(float number)
272 =========
273 */
274 extern unsigned short video_resolutions[][2];
275 void VM_M_getresolution(void)
276 {
277         int nr;
278         VM_SAFEPARMCOUNT(1, VM_getresolution);
279
280         nr = (int)PRVM_G_FLOAT(OFS_PARM0);
281
282
283         PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
284         PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
285         PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
286 }
287
288 /*
289 =========
290 VM_M_findkeysforcommand
291
292 string  findkeysforcommand(string command)
293
294 the returned string is an altstring
295 =========
296 */
297 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
298
299 void M_FindKeysForCommand(const char *command, int *keys);
300 void VM_M_findkeysforcommand(void)
301 {
302         const char *cmd;
303         char ret[VM_STRINGTEMP_LENGTH];
304         int keys[NUMKEYS];
305         int i;
306
307         VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
308
309         cmd = PRVM_G_STRING(OFS_PARM0);
310
311         VM_CheckEmptyString(cmd);
312
313         M_FindKeysForCommand(cmd, keys);
314
315         ret[0] = 0;
316         for(i = 0; i < NUMKEYS; i++)
317                 strlcat(ret, va(" \'%i\'", keys[i]), sizeof(ret));
318
319         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(ret);
320 }
321
322 /*
323 =========
324 VM_M_getserverliststat
325
326 float   getserverliststat(float type)
327 =========
328 */
329 /*
330         type:
331 0       serverlist_viewcount
332 1   serverlist_totalcount
333 2       masterquerycount
334 3       masterreplycount
335 4       serverquerycount
336 5       serverreplycount
337 6       sortfield
338 7       sortdescending
339 */
340 void VM_M_getserverliststat( void )
341 {
342         int type;
343         VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
344
345         PRVM_G_FLOAT( OFS_RETURN ) = 0;
346
347         type = (int)PRVM_G_FLOAT( OFS_PARM0 );
348         switch(type)
349         {
350         case 0:
351                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_viewcount;
352                 return;
353         case 1:
354                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_cachecount;
355         case 2:
356                 PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
357                 return;
358         case 3:
359                 PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
360                 return;
361         case 4:
362                 PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
363                 return;
364         case 5:
365                 PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
366                 return;
367         case 6:
368                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortbyfield;
369                 return;
370         case 7:
371                 PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortdescending;
372                 return;
373         default:
374                 VM_Warning( "VM_M_getserverliststat: bad type %i!\n", type );
375         }
376 }
377
378 /*
379 ========================
380 VM_M_resetserverlistmasks
381
382 resetserverlistmasks()
383 ========================
384 */
385 void VM_M_resetserverlistmasks( void )
386 {
387         ServerList_ResetMasks();
388 }
389
390
391 /*
392 ========================
393 VM_M_setserverlistmaskstring
394
395 setserverlistmaskstring(float mask, float fld, string str, float op)
396 0-511           and
397 512 - 1024      or
398 ========================
399 */
400 void VM_M_setserverlistmaskstring( void )
401 {
402         const char *str;
403         int masknr;
404         serverlist_mask_t *mask;
405         int field;
406
407         VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmaskstring );
408         str = PRVM_G_STRING( OFS_PARM2 );
409
410         masknr = (int)PRVM_G_FLOAT( OFS_PARM0 );
411         if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
412                 mask = &serverlist_andmasks[masknr];
413         else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
414                 mask = &serverlist_ormasks[masknr - 512 ];
415         else
416         {
417                 VM_Warning( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
418                 return;
419         }
420
421         field = (int) PRVM_G_FLOAT( OFS_PARM1 );
422
423         switch( field ) {
424                 case SLIF_CNAME:
425                         strlcpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
426                         break;
427                 case SLIF_NAME:
428                         strlcpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name)  );
429                         break;
430                 case SLIF_MAP:
431                         strlcpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map)  );
432                         break;
433                 case SLIF_MOD:
434                         strlcpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod)  );
435                         break;
436                 case SLIF_GAME:
437                         strlcpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game)  );
438                         break;
439                 default:
440                         VM_Warning( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
441                         return;
442         }
443
444         mask->active = true;
445         mask->tests[field] = (serverlist_maskop_t)((int)PRVM_G_FLOAT( OFS_PARM3 ));
446 }
447
448 /*
449 ========================
450 VM_M_setserverlistmasknumber
451
452 setserverlistmasknumber(float mask, float fld, float num, float op)
453
454 0-511           and
455 512 - 1024      or
456 ========================
457 */
458 void VM_M_setserverlistmasknumber( void )
459 {
460         int number;
461         serverlist_mask_t *mask;
462         int     masknr;
463         int field;
464         VM_SAFEPARMCOUNT( 4, VM_M_setserverlistmasknumber );
465
466         masknr = (int)PRVM_G_FLOAT( OFS_PARM0 );
467         if( masknr >= 0 && masknr <= SERVERLIST_ANDMASKCOUNT )
468                 mask = &serverlist_andmasks[masknr];
469         else if( masknr >= 512 && masknr - 512 <= SERVERLIST_ORMASKCOUNT )
470                 mask = &serverlist_ormasks[masknr - 512 ];
471         else
472         {
473                 VM_Warning( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
474                 return;
475         }
476
477         number = (int)PRVM_G_FLOAT( OFS_PARM2 );
478         field = (int) PRVM_G_FLOAT( OFS_PARM1 );
479
480         switch( field ) {
481                 case SLIF_MAXPLAYERS:
482                         mask->info.maxplayers = number;
483                         break;
484                 case SLIF_NUMPLAYERS:
485                         mask->info.numplayers = number;
486                         break;
487                 case SLIF_PING:
488                         mask->info.ping = number;
489                         break;
490                 case SLIF_PROTOCOL:
491                         mask->info.protocol = number;
492                         break;
493                 default:
494                         VM_Warning( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
495                         return;
496         }
497
498         mask->active = true;
499         mask->tests[field] = (serverlist_maskop_t)((int)PRVM_G_FLOAT( OFS_PARM3 ));
500 }
501
502
503 /*
504 ========================
505 VM_M_resortserverlist
506
507 resortserverlist
508 ========================
509 */
510 void VM_M_resortserverlist( void )
511 {
512         ServerList_RebuildViewList();
513 }
514
515 /*
516 =========
517 VM_M_getserverliststring
518
519 string  getserverliststring(float field, float hostnr)
520 =========
521 */
522 void VM_M_getserverliststring(void)
523 {
524         serverlist_entry_t *cache;
525         int hostnr;
526
527         VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
528
529         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
530
531         hostnr = (int)PRVM_G_FLOAT(OFS_PARM1);
532
533         if(hostnr < 0 || hostnr >= serverlist_viewcount)
534         {
535                 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
536                 return;
537         }
538         cache = serverlist_viewlist[hostnr];
539         switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
540                 case SLIF_CNAME:
541                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
542                         break;
543                 case SLIF_NAME:
544                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
545                         break;
546                 case SLIF_GAME:
547                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
548                         break;
549                 case SLIF_MOD:
550                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
551                         break;
552                 case SLIF_MAP:
553                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
554                         break;
555                 // TODO remove this again
556                 case 1024:
557                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
558                         break;
559                 case 1025:
560                         PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
561                         break;
562                 default:
563                         Con_Print("VM_M_getserverliststring: bad field number passed!\n");
564         }
565 }
566
567 /*
568 =========
569 VM_M_getserverlistnumber
570
571 float   getserverlistnumber(float field, float hostnr)
572 =========
573 */
574 void VM_M_getserverlistnumber(void)
575 {
576         serverlist_entry_t *cache;
577         int hostnr;
578
579         VM_SAFEPARMCOUNT(2, VM_M_getserverliststring);
580
581         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
582
583         hostnr = (int)PRVM_G_FLOAT(OFS_PARM1);
584
585         if(hostnr < 0 || hostnr >= serverlist_viewcount)
586         {
587                 Con_Print("VM_M_getserverliststring: bad hostnr passed!\n");
588                 return;
589         }
590         cache = serverlist_viewlist[hostnr];
591         switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
592                 case SLIF_MAXPLAYERS:
593                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
594                         break;
595                 case SLIF_NUMPLAYERS:
596                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
597                         break;
598                 case SLIF_PING:
599                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
600                         break;
601                 case SLIF_PROTOCOL:
602                         PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
603                         break;
604                 default:
605                         Con_Print("VM_M_getserverlistnumber: bad field number passed!\n");
606         }
607 }
608
609 /*
610 ========================
611 VM_M_setserverlistsort
612
613 setserverlistsort(float field, float descending)
614 ========================
615 */
616 void VM_M_setserverlistsort( void )
617 {
618         VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
619
620         serverlist_sortbyfield = (serverlist_infofield_t)((int)PRVM_G_FLOAT( OFS_PARM0 ));
621         serverlist_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
622 }
623
624 /*
625 ========================
626 VM_M_refreshserverlist
627
628 refreshserverlist()
629 ========================
630 */
631 void VM_M_refreshserverlist( void )
632 {
633         VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
634         ServerList_QueryList(true, false);
635 }
636
637 /*
638 ========================
639 VM_M_getserverlistindexforkey
640
641 float getserverlistindexforkey(string key)
642 ========================
643 */
644 void VM_M_getserverlistindexforkey( void )
645 {
646         const char *key;
647         VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
648
649         key = PRVM_G_STRING( OFS_PARM0 );
650         VM_CheckEmptyString( key );
651
652         if( !strcmp( key, "cname" ) )
653                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
654         else if( !strcmp( key, "ping" ) )
655                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PING;
656         else if( !strcmp( key, "game" ) )
657                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_GAME;
658         else if( !strcmp( key, "mod" ) )
659                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MOD;
660         else if( !strcmp( key, "map" ) )
661                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAP;
662         else if( !strcmp( key, "name" ) )
663                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NAME;
664         else if( !strcmp( key, "maxplayers" ) )
665                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_MAXPLAYERS;
666         else if( !strcmp( key, "numplayers" ) )
667                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_NUMPLAYERS;
668         else if( !strcmp( key, "protocol" ) )
669                 PRVM_G_FLOAT( OFS_RETURN ) = SLIF_PROTOCOL;
670         else
671                 PRVM_G_FLOAT( OFS_RETURN ) = -1;
672 }
673
674 /*
675 ========================
676 VM_M_addwantedserverlistkey
677
678 addwantedserverlistkey(string key)
679 ========================
680 */
681 void VM_M_addwantedserverlistkey( void )
682 {
683         VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
684 }
685
686 /*
687 ===============================================================================
688 MESSAGE WRITING
689
690 used only for client and menu
691 severs uses VM_SV_...
692
693 Write*(* data, float type, float to)
694
695 ===============================================================================
696 */
697
698 #define MSG_BROADCAST   0               // unreliable to all
699 #define MSG_ONE                 1               // reliable to one (msg_entity)
700 #define MSG_ALL                 2               // reliable to all
701 #define MSG_INIT                3               // write to the init string
702
703 sizebuf_t *VM_WriteDest (void)
704 {
705         int             dest;
706         int             destclient;
707
708         if(!sv.active)
709                 PRVM_ERROR("VM_WriteDest: game is not server (%s)", PRVM_NAME);
710
711         dest = (int)PRVM_G_FLOAT(OFS_PARM1);
712         switch (dest)
713         {
714         case MSG_BROADCAST:
715                 return &sv.datagram;
716
717         case MSG_ONE:
718                 destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
719                 if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active || !svs.clients[destclient].netconnection)
720                         PRVM_ERROR("VM_clientcommand: %s: invalid client !", PRVM_NAME);
721
722                 return &svs.clients[destclient].netconnection->message;
723
724         case MSG_ALL:
725                 return &sv.reliable_datagram;
726
727         case MSG_INIT:
728                 return &sv.signon;
729
730         default:
731                 PRVM_ERROR ("WriteDest: bad destination");
732                 break;
733         }
734
735         return NULL;
736 }
737
738 void VM_M_WriteByte (void)
739 {
740         MSG_WriteByte (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
741 }
742
743 void VM_M_WriteChar (void)
744 {
745         MSG_WriteChar (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
746 }
747
748 void VM_M_WriteShort (void)
749 {
750         MSG_WriteShort (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
751 }
752
753 void VM_M_WriteLong (void)
754 {
755         MSG_WriteLong (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
756 }
757
758 void VM_M_WriteAngle (void)
759 {
760         MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
761 }
762
763 void VM_M_WriteCoord (void)
764 {
765         MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
766 }
767
768 void VM_M_WriteString (void)
769 {
770         MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0));
771 }
772
773 void VM_M_WriteEntity (void)
774 {
775         MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
776 }
777
778 //string(void) getextresponse = #624; // returns the next extResponse packet that was sent to this client
779 void VM_M_getextresponse (void)
780 {
781         VM_SAFEPARMCOUNT(0,VM_argv);
782
783         if (net_extresponse_count <= 0)
784                 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
785         else
786         {
787                 int first;
788                 --net_extresponse_count;
789                 first = (net_extresponse_last + NET_EXTRESPONSE_MAX - net_extresponse_count) % NET_EXTRESPONSE_MAX;
790                 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(net_extresponse[first]);
791         }
792 }
793
794 prvm_builtin_t vm_m_builtins[] = {
795         0, // to be consistent with the old vm
796         // common builtings (mostly)
797         VM_checkextension,
798         VM_error,
799         VM_objerror,
800         VM_print,
801         VM_bprint,
802         VM_sprint,
803         VM_centerprint,
804         VM_normalize,
805         VM_vlen,
806         VM_vectoyaw,    // #10
807         VM_vectoangles,
808         VM_random,
809         VM_localcmd,
810         VM_cvar,
811         VM_cvar_set,
812         VM_dprint,
813         VM_ftos,
814         VM_fabs,
815         VM_vtos,
816         VM_etos,                // 20
817         VM_stof,
818         VM_spawn,
819         VM_remove,
820         VM_find,
821         VM_findfloat,
822         VM_findchain,
823         VM_findchainfloat,
824         VM_M_precache_file,
825         VM_M_precache_sound,
826         VM_coredump,    // 30
827         VM_traceon,
828         VM_traceoff,
829         VM_eprint,
830         VM_rint,
831         VM_floor,
832         VM_ceil,
833         VM_nextent,
834         VM_sin,
835         VM_cos,
836         VM_sqrt,                // 40
837         VM_randomvec,
838         VM_registercvar,
839         VM_min,
840         VM_max,
841         VM_bound,
842         VM_pow,
843         VM_copyentity,
844         VM_fopen,
845         VM_fclose,
846         VM_fgets,               // 50
847         VM_fputs,
848         VM_strlen,
849         VM_strcat,
850         VM_substring,
851         VM_stov,
852         VM_strzone,
853         VM_strunzone,
854         VM_tokenize,
855         VM_argv,
856         VM_isserver,    // 60
857         VM_clientcount,
858         VM_clientstate,
859         VM_clcommand,
860         VM_changelevel,
861         VM_localsound,
862         VM_getmousepos,
863         VM_gettime,
864         VM_loadfromdata,
865         VM_loadfromfile,
866         VM_modulo,              // 70
867         VM_cvar_string,
868         VM_crash,
869         VM_stackdump,   // 73
870         VM_search_begin,
871         VM_search_end,
872         VM_search_getsize,
873         VM_search_getfilename, // 77
874         VM_chr,
875         VM_itof,
876         VM_ftoe,                // 80
877         VM_itof,                // isString
878         VM_altstr_count,
879         VM_altstr_prepare,
880         VM_altstr_get,
881         VM_altstr_set,
882         VM_altstr_ins,
883         VM_findflags,
884         VM_findchainflags,
885         VM_cvar_defstring, // 89
886         0, // 90
887         e10,                    // 100
888         e100,                   // 200
889         e100,                   // 300
890         e100,                   // 400
891         // msg functions
892         VM_M_WriteByte,
893         VM_M_WriteChar,
894         VM_M_WriteShort,
895         VM_M_WriteLong,
896         VM_M_WriteAngle,
897         VM_M_WriteCoord,
898         VM_M_WriteString,
899         VM_M_WriteEntity,       // 408
900         0,
901         0,                              // 410
902         e10,                    // 420
903         e10,                    // 430
904         e10,                    // 440
905         e10,                    // 450
906         // draw functions
907         VM_iscachedpic,
908         VM_precache_pic,
909         VM_freepic,
910         VM_drawcharacter,
911         VM_drawstring,
912         VM_drawpic,
913         VM_drawfill,
914         VM_drawsetcliparea,
915         VM_drawresetcliparea,
916         VM_getimagesize,// 460
917         VM_cin_open,
918         VM_cin_close,
919         VM_cin_setstate,
920         VM_cin_getstate,
921         VM_cin_restart, // 465
922         VM_drawline,    // 466
923         0,0,0,0,        // 470
924         VM_asin,                                        // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
925         VM_acos,                                        // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
926         VM_atan,                                        // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
927         VM_atan2,                                       // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
928         VM_tan,                                         // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
929         VM_strlennocol,                         // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
930         VM_strdecolorize,                       // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
931         0,0,0,                  // 480
932         e10,                    // 490
933         e10,                    // 500
934         e100,                   // 600
935         // menu functions
936         VM_M_setkeydest,
937         VM_M_getkeydest,
938         VM_M_setmousetarget,
939         VM_M_getmousetarget,
940         VM_M_callfunction,
941         VM_M_writetofile,
942         VM_M_isfunction,
943         VM_M_getresolution,
944         VM_keynumtostring,
945         VM_M_findkeysforcommand,// 610
946         VM_M_getserverliststat,
947         VM_M_getserverliststring,
948         VM_parseentitydata,
949         VM_stringtokeynum,
950         VM_M_resetserverlistmasks,
951         VM_M_setserverlistmaskstring,
952         VM_M_setserverlistmasknumber,
953         VM_M_resortserverlist,
954         VM_M_setserverlistsort,
955         VM_M_refreshserverlist,
956         VM_M_getserverlistnumber,
957         VM_M_getserverlistindexforkey,
958         VM_M_addwantedserverlistkey, // 623
959         VM_M_getextresponse
960 };
961
962 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
963
964 void VM_M_Cmd_Init(void)
965 {
966         VM_Cmd_Init();
967 }
968
969 void VM_M_Cmd_Reset(void)
970 {
971         //VM_Cmd_Init();
972         VM_Cmd_Reset();
973 }