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