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