]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multilag.cpp
More progress
[taylor/freespace2.git] / src / network / multilag.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/multilag.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * $Log$
8  * Revision 1.4  2002/05/26 20:49:54  theoddone33
9  * More progress
10  *
11  * Revision 1.3  2002/05/26 20:22:48  theoddone33
12  * Most of network/ works
13  *
14  * Revision 1.2  2002/05/07 03:16:47  theoddone33
15  * The Great Newline Fix
16  *
17  * Revision 1.1.1.1  2002/05/03 03:28:10  root
18  * Initial import.
19  *
20  * 
21  * 4     11/19/98 8:03a Dave
22  * Full support for D3-style reliable sockets. Revamped packet lag/loss
23  * system, made it receiver side and at the lowest possible level.
24  * 
25  * 3     11/17/98 11:12a Dave
26  * Removed player identification by address. Now assign explicit id #'s.
27  * 
28  * 2     10/07/98 10:53a Dave
29  * Initial checkin.
30  * 
31  * 1     10/07/98 10:50a Dave
32  * 
33  * 15    6/05/98 9:54a Lawrance
34  * OEM changes
35  * 
36  * 14    4/27/98 6:02p Dave
37  * Modify how missile scoring works. Fixed a team select ui bug. Speed up
38  * multi_lag system. Put in new main hall.
39  * 
40  * 13    4/18/98 5:00p Dave
41  * Put in observer zoom key. Made mission sync screen more informative.
42  * 
43  * 12    4/06/98 12:37a Lawrance
44  * fix compile bug with demo
45  * 
46  * 11    4/04/98 8:42p Dave
47  * Tested and debugged UDP reliable socket layer. Modified lag system to
48  * take this into account. 
49  * 
50  * 10    4/02/98 6:29p Lawrance
51  * compile out multilag code for demo
52  * 
53  * 9     3/14/98 2:48p Dave
54  * Cleaned up observer joining code. Put in support for file xfers to
55  * ingame joiners (observers or not). Revamped and reinstalled pseudo
56  * lag/loss system.
57  * 
58  * 8     1/11/98 10:03p Allender
59  * removed <winsock.h> from headers which included it.  Made psnet_socket
60  * type which is defined just as SOCKET type is.
61  * 
62  * 7     12/29/97 5:21p Dave
63  * Put in object update sequencing for multiplayer.
64  * 
65  * 6     12/16/97 6:17p Dave
66  * Put in primary weapon support for multiplayer weapon select screen.
67  * 
68  * 5     12/10/97 4:45p Dave
69  * Added in more detailed support for multiplayer packet lag/loss. Fixed
70  * some multiplayer stuff. Added some controls to the standalone.
71  * 
72  * 4     12/01/97 4:59p Dave
73  * Synchronized multiplayer debris objects. Put in pilot popup in main
74  * hall. Optimized simulated multiplayer lag module. Fixed a potential
75  * file_xfer bug.
76  * 
77  * 3     11/28/97 7:04p Dave
78  * Emergency checkin due to big system crash.
79  * 
80  * 2     11/28/97 5:06p Dave
81  * Put in facilities for simulating multiplayer lag.
82  * 
83  * 1     11/28/97 4:38p Dave
84  * Initial Revision
85  * 
86  * $NoKeywords: $
87  */
88
89 #ifndef PLAT_UNIX
90 #include <winsock.h>
91 #include <wsipx.h>
92 #else
93 #include <sys/time.h>
94 #include <sys/types.h>
95 #include <sys/socket.h>
96 #include <netinet/in.h>
97 #include <arpa/inet.h>
98 #include <netdb.h>
99 #include <unistd.h>
100 #endif
101 #include "pstypes.h"
102 #include "multi.h"
103 #include "multilag.h"
104 #include "cmdline.h"
105 #include "timer.h"
106 #include "linklist.h"
107
108 // ----------------------------------------------------------------------------------------------------
109 // LAGLOSS DEFINES/VARS
110 //
111
112 // default LAGLOSS values
113 #define MULTI_LAGLOSS_DEF_LAG                           (-1)
114 #define MULTI_LAGLOSS_DEF_LAGMIN                        (-1)
115 #define MULTI_LAGLOSS_DEF_LAGMAX                        (-1)
116 #define MULTI_LAGLOSS_DEF_LOSS                  (-1.0f)
117 #define MULTI_LAGLOSS_DEF_LOSSMIN               (-1.0f)
118 #define MULTI_LAGLOSS_DEF_LOSSMAX               (-1.0f)
119 #define MULTI_LAGLOSS_DEF_STREAK                        (2500)
120
121 // if we're running
122 int Multi_lag_inited = 0;
123
124 // lag values (base - max and min)
125 int Multi_lag_base = -1;
126 int Multi_lag_min = -1;
127 int Multi_lag_max = -1;
128
129 // packet loss values (base - max and min)
130 float Multi_loss_base = -1.0f;
131 float Multi_loss_min = -1.0f;
132 float Multi_loss_max = -1.0f;
133
134 // streaks for lagging
135 int Multi_streak_stamp = -1;                            // timestamp telling when the streak of a certain lag is done
136 int Multi_streak_time = 0;                                      // how long each streak will last
137 int Multi_current_streak = -1;                  // what lag the current streak has
138
139 // struct for buffering stuff on receives
140 typedef struct lag_buf {
141         ubyte data[700];                                                        // the data from the packet
142         int data_len;                                                           // length of the data
143         uint socket;                                                            // this can be either a PSNET_SOCKET or a PSNET_SOCKET_RELIABLE
144         int stamp;                                                                      // when this expires, make this packet available        
145         SOCKADDR_IN ip_addr;                                            // ip address when in TCP
146 #ifndef PLAT_UNIX
147         SOCKADDR_IPX ipx_addr;                                  // ipx address when in IPX mode
148 #endif
149
150         struct  lag_buf * prev;                         // prev in the list
151         struct  lag_buf * next;                         // next in the list
152 } lag_buf;
153
154 // lag buffers - malloced
155 #ifdef NDEBUG
156         #define MAX_LAG_BUFFERS                 1               // only 1 buffer in non-debug builds
157 #else
158         #define MAX_LAG_BUFFERS                 1000
159 #endif
160 lag_buf *Lag_buffers[MAX_LAG_BUFFERS];
161 int Lag_buf_count = 0;                                          // how many lag_buf's are currently in use
162
163 lag_buf Lag_free_list;
164 lag_buf Lag_used_list;
165
166
167 // ----------------------------------------------------------------------------------------------------
168 // LAGLOSS FORWARD DECLARATIONS
169 //
170
171 // get a value to lag a packet with (in ms)
172 int multi_lag_get_random_lag();
173
174 // boolean yes or no - should this packet be lost?
175 int multi_lag_should_be_lost();             
176
177 // get a free packet buffer, return NULL on fail
178 lag_buf *multi_lag_get_free();
179
180 // put a lag buffer back
181 void multi_lag_put_free(lag_buf *buf);
182
183 // ----------------------------------------------------------------------------------------------------
184 // LAGLOSS FUNCTIONS
185 //
186
187 void multi_lag_init()
188 {       
189         // never do lag in a non-debug build
190 #if defined(NDEBUG) || !defined(MULTI_USE_LAG)
191         Multi_lag_inited = 0;
192 #else
193         int idx;
194
195         // if we're already inited, don't do anything
196         if(Multi_lag_inited){
197                 return;
198         }
199
200         // try and allocate lag bufs
201         for(idx=0; idx<MAX_LAG_BUFFERS; idx++){
202                 Lag_buffers[idx] = (lag_buf*)malloc(sizeof(lag_buf));
203                 if(Lag_buffers[idx] == NULL){
204                         return;
205                 }
206         }
207
208         // initialize lag buffer lists
209         list_init( &Lag_free_list );
210         list_init( &Lag_used_list );
211
212         // Link all object slots into the free list
213         for (idx=0; idx<MAX_LAG_BUFFERS; idx++) {
214                 list_append(&Lag_free_list, Lag_buffers[idx]);
215         }
216         
217         // set the default lag values
218         Multi_lag_base = MULTI_LAGLOSS_DEF_LAG;
219         Multi_lag_min = MULTI_LAGLOSS_DEF_LAGMIN;
220         Multi_lag_max = MULTI_LAGLOSS_DEF_LAGMAX;
221
222         // set the default loss values
223         Multi_loss_base = MULTI_LAGLOSS_DEF_LOSS;
224         Multi_loss_min  = MULTI_LAGLOSS_DEF_LOSSMIN;
225         Multi_loss_max = MULTI_LAGLOSS_DEF_LOSSMAX;
226
227         // set the default lag streak time      
228         Multi_streak_time = MULTI_LAGLOSS_DEF_STREAK;
229         
230         Multi_lag_inited = 1;
231 #endif
232 }
233
234 void multi_lag_close()
235 {       
236         int idx;
237
238         // if we're not inited already, don't do anything
239         if(!Multi_lag_inited){
240                 return;
241         }       
242
243         // free up lag buffers
244         for(idx=0; idx<MAX_LAG_BUFFERS; idx++){
245                 if(Lag_buffers[idx] != NULL){
246                         free(Lag_buffers[idx]);
247                         Lag_buffers[idx] = NULL;
248                 }
249         }
250
251         Multi_lag_inited = 0;
252 }
253
254 // select for multi_lag
255 int multi_lag_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *except_fds, timeval *timeout)
256 {               
257 #ifdef PLAT_UNIX
258         STUB_FUNCTION;
259 #else
260         char t_buf[1024];
261         int t_from_len;
262         SOCKADDR_IN ip_addr;
263 #ifndef PLAT_UNIX
264         SOCKADDR_IPX ipx_addr;
265 #endif
266         int ret_val;
267         lag_buf *moveup, *item;
268
269         Assert(readfds != NULL);
270         Assert(writefds == NULL);
271         Assert(except_fds == NULL);
272
273         // clear out addresses
274         memset(&ip_addr, 0, sizeof(SOCKADDR_IN));
275 #ifndef PLAT_UNIX
276         memset(&ipx_addr, 0, sizeof(SOCKADDR_IPX));
277 #endif
278
279         // if there's data on the socket, read it
280         if(select(nfds, readfds, writefds, except_fds, timeout)){               
281                 // read the data and stuff it
282                 if(Tcp_active){                                         
283                         t_from_len = sizeof(SOCKADDR_IN);
284                         ret_val = recvfrom(readfds->fd_array[0], t_buf, 1024, 0, (SOCKADDR*)&ip_addr, &t_from_len);
285 #ifndef PLAT_UNIX
286                 } else {
287                         t_from_len = sizeof(SOCKADDR_IPX);
288                         ret_val = recvfrom(readfds->fd_array[0], t_buf, 1024, 0, (SOCKADDR*)&ipx_addr, &t_from_len);
289 #endif
290                 }
291                         
292                 // wacky socket error
293                 if(ret_val == SOCKET_ERROR){
294                         return SOCKET_ERROR;
295                 }
296
297                 // if we should be dropping this packet
298                 if(!multi_lag_should_be_lost()){
299                         // get a free packet buf and stuff the data
300                         item = multi_lag_get_free();
301                         if(item){
302                                 Assert(ret_val < 700);
303                                 memcpy(item->data, t_buf, ret_val);                     
304                                 item->data_len = ret_val;
305                                 item->ip_addr = ip_addr;
306 #ifndef PLAT_UNIX
307                                 item->ipx_addr = ipx_addr;
308 #endif
309                                 item->socket = readfds->fd_array[0];
310                                 item->stamp = timestamp(multi_lag_get_random_lag());
311                         }               
312                 }
313         }
314
315         // always unset the readfds
316         readfds->fd_count = 0;
317
318         // now determine if we have any pending packets - find the first one
319         // NOTE : this _could_ be the packet we just read. In fact, with a 0 lag, this will always be the case
320         moveup=GET_FIRST(&Lag_used_list);
321         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
322                 // if the timestamp has elapsed and we have a matching socket
323                 if((readfds->fd_array[0] == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
324                         // set this so we think select returned yes
325                         readfds->fd_count = 1;
326                         return 1;
327                 }
328
329                 moveup = GET_NEXT(moveup);
330         }
331
332 #endif
333         // no data
334         return 0;
335 }
336
337 // recvfrom for multilag
338 int multi_lag_recvfrom(uint s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
339 {
340         lag_buf *moveup = NULL;
341         lag_buf *item = NULL;
342
343         // now determine if we have any pending packets - find the first one
344         moveup=GET_FIRST(&Lag_used_list);
345         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
346                 // if the timestamp has elapsed
347                 if((s == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
348                         item = moveup;
349                         break;
350                 }
351
352                 moveup = GET_NEXT(moveup);
353         }
354
355         // if this happens, it means that the multi_lag_select() returned an improper value
356         Assert(item);
357         // stuff the data
358         Assert(item->data_len <= len);
359         memcpy(buf, item->data, item->data_len);
360         if(Tcp_active){
361                 memcpy(from, &item->ip_addr, sizeof(SOCKADDR_IN));
362 #ifndef PLAT_UNIX
363         } else {
364                 memcpy(from, &item->ipx_addr, sizeof(SOCKADDR_IPX));
365 #endif
366         }
367
368         // stick the item back on the free list
369         multi_lag_put_free(item);
370
371         // return the size in bytes
372         return item->data_len;
373 }
374
375 // ----------------------------------------------------------------------------------------------------
376 // LAGLOSS FORWARD DEFINITIONS
377 //
378
379 int multi_lag_get_random_lag()
380 {
381         // first determine the percentage we'll be checking against
382         int ret;
383         int mod;        
384
385         // if the lag system isn't inited, don't do anything (no lag)
386         if(!Multi_lag_inited){
387                 return 0;
388         }
389                 
390         // pick a value
391         // see if we should be going up or down (loss max/loss min)
392         mod = 0;
393         if((float)rand()/(float)RAND_MAX < 0.5){
394                 // down
395                 if(Multi_lag_min >= 0){
396                         mod = - (int)((float)(Multi_lag_base - Multi_lag_min) * ((float)rand()/(float)RAND_MAX));
397                 }
398         } else {
399                 // up
400                 if(Multi_lag_max >= 0){
401                         mod = (int)((float)(Multi_lag_max - Multi_lag_base) * ((float)rand()/(float)RAND_MAX));
402                 }
403         }
404         
405         // if the current streak has elapsed, calculate a new one
406         if((Multi_streak_stamp == -1) || (timestamp_elapsed(Multi_streak_stamp))){
407                 // timestamp the new streak
408                 Multi_streak_stamp = timestamp(Multi_streak_time);
409
410                 // set the return value
411                 ret = Multi_lag_base + mod;
412                 
413                 // set the lag value of this current streak
414                 Multi_current_streak = ret;
415         } 
416         // otherwise use the lag for the current streak
417         else {
418                 ret = Multi_current_streak;
419         }
420                         
421         return ret;     
422 }
423
424 // this _may_ be a bit heavyweight, but it _is_ debug code
425 int multi_lag_should_be_lost()
426 {       
427         // first determine the percentage we'll be checking against
428         float mod;      
429
430         // if the lag system isn't inited, don't do anything
431         if(!Multi_lag_inited){
432                 return 0;
433         }
434                 
435         // see if we should be going up or down (loss max/loss min)
436         mod = 0.0f;
437         if((float)rand()/(float)RAND_MAX < 0.5){
438                 // down
439                 if(Multi_loss_min >= 0.0f){
440                         mod = - ((Multi_loss_base - Multi_loss_min) * ((float)rand()/(float)RAND_MAX));
441                 }
442         } else {
443                 // up
444                 if(Multi_loss_max >= 0.0f){
445                         mod = ((Multi_loss_max - Multi_loss_base) * ((float)rand()/(float)RAND_MAX));
446                 }
447         }       
448         
449         if((float)rand()/(float)RAND_MAX <= Multi_loss_base + mod){
450                 return 1;
451         }       
452
453         return 0;
454 }
455
456 // get a free packet buffer, return NULL on fail
457 lag_buf *multi_lag_get_free()
458 {
459         lag_buf *lagp;
460
461         // if we're out of buffers
462         if(Lag_buf_count >= MAX_LAG_BUFFERS){
463                 nprintf(("Network", "Out of lag buffers!\n"));
464                 return NULL;
465         }
466
467         // get a free item
468         lagp = GET_FIRST(&Lag_free_list);
469         Assert( lagp != &Lag_free_list );               // shouldn't have the dummy element
470
471         // remove trailp from the free list
472         list_remove( &Lag_free_list, lagp );
473         
474         // insert trailp onto the end of used list
475         list_append( &Lag_used_list, lagp );
476
477         // increase the count
478         Lag_buf_count++;
479         return lagp;
480 }
481
482 // put a lag buffer back
483 void multi_lag_put_free(lag_buf *buf)
484 {
485         // remove objp from the used list
486         list_remove( &Lag_used_list, buf);
487
488         // add objp to the end of the free
489         list_append( &Lag_free_list, buf );
490
491         // decrement counter
492         Lag_buf_count--;
493 }
494
495 void multi_lagloss_dcf()
496 {
497         // if the lag system isn't inited, don't do anything
498         if(!Multi_lag_inited){
499                 dc_printf("Lag System Not Initialized!\n");
500                 return;
501         }
502
503         // display all available commands
504         dc_printf("Usage :\nlag <ms>  (-1 to disable)\nlag_min <ms>\nlag_max <ms>\nloss <0-100>  (-1 to disable)\nloss_min <0-100>\nloss_max <0-100>\nlag_streak <ms>\nlagloss\n");
505
506         // display lag settings
507         dc_printf("Lag : ");            
508         dc_printf("\n   Base %d\n   Min %d\n   Max %d\n   Streak %d\n", Multi_lag_base, Multi_lag_min, Multi_lag_max, Multi_streak_time);       
509
510         // display loss settings
511         dc_printf("Loss : ");           
512         dc_printf("\n   Base %f\n   Min %f\n   Max %f\n", Multi_loss_base, Multi_loss_min, Multi_loss_max);     
513 }
514
515 DCF(lag, "")
516 {
517         // if the lag system isn't inited, don't do anything
518         if(!Multi_lag_inited){
519                 dc_printf("Lag System Not Initialized!\n");
520                 return;
521         }
522
523         dc_get_arg(ARG_INT);            
524         // parse the argument and change things around accordingly
525         if(Dc_arg_type & ARG_INT){                      
526                 if(Dc_arg_int < 0){
527                         // switch the lag sim off
528                         Multi_lag_base = -1;
529                         Multi_lag_min = -1;
530                         Multi_lag_max = -1;
531                         dc_printf("Turning simulated lag off\n");
532                         multi_lagloss_dcf();
533                 } else if((Multi_lag_max >= 0) && (Dc_arg_int > Multi_lag_max)){
534                         dc_printf("Base value greater than max value, ignoring...");
535                 } else if((Multi_lag_min >= 0) && (Dc_arg_int < Multi_lag_min)){
536                         dc_printf("Base value smaller than min value, ignoring...");
537                 } else {
538                         Multi_lag_base = Dc_arg_int;
539                         multi_lagloss_dcf();
540                 }
541         }       
542 }
543
544 DCF(lag_min, "")
545 {
546         // if the lag system isn't inited, don't do anything
547         if(!Multi_lag_inited){
548                 dc_printf("Lag System Not Initialized!\n");
549                 return;
550         }
551
552         dc_get_arg(ARG_INT);            
553         // parse the argument and change things around accordingly
554         if(Dc_arg_type & ARG_INT){                      
555                 if(Dc_arg_int > Multi_lag_base){
556                         dc_printf("Min value greater than base value, ignoring...");
557                 } else {
558                         if(Dc_arg_int < 0){
559                                 Multi_lag_min = -1;
560                         } else {
561                                 Multi_lag_min = Dc_arg_int;
562                         }
563                         multi_lagloss_dcf();
564                 }
565         }                       
566 }
567
568 DCF(lag_max, "")
569 {
570         // if the lag system isn't inited, don't do anything
571         if(!Multi_lag_inited){
572                 dc_printf("Lag System Not Initialized!\n");
573                 return;
574         }
575
576         // parse the argument and change things around accordingly
577         dc_get_arg(ARG_INT);
578         if(Dc_arg_type & ARG_INT){                      
579                 if((Dc_arg >=0) && (Dc_arg_int < Multi_lag_base)){
580                         dc_printf("Max value smaller than base value, ignoring...");
581                 } else {
582                         if(Dc_arg_int < 0){
583                                 Multi_lag_max = -1;
584                         } else {
585                                 Multi_lag_max = Dc_arg_int;
586                         }
587                         multi_lagloss_dcf();
588                 }
589         }               
590 }
591
592 DCF(loss, "")
593 {
594         // if the lag system isn't inited, don't do anything
595         if(!Multi_lag_inited){
596                 dc_printf("Lag System Not Initialized!\n");
597                 return;
598         }
599
600         // parse the argument and change things around accordingly
601         dc_get_arg(ARG_INT);
602         if(Dc_arg_type & ARG_INT){
603                 float val = (float)Dc_arg_int / 100.0f;
604                         
605                 if(Dc_arg_int > 100){
606                         dc_printf("Illegal loss base value, ignoring...");
607                 } else if(Dc_arg_int < 0){
608                         // switch the loss sim off
609                         dc_printf("Turning simulated loss off\n");
610                         Multi_loss_base = -1.0f;
611                         Multi_loss_min = -1.0f;
612                         Multi_loss_max = -1.0f;
613                         multi_lagloss_dcf();
614                 } else if((Multi_loss_max >= 0.0f) && (val > Multi_loss_max)){
615                         dc_printf("Base value greater than max value, ignoring...");
616                 } else if((Multi_loss_min >= 0.0f) && (val < Multi_loss_min)){
617                         dc_printf("Base value smaller than min value, ignoring...");
618                 } else {
619                         Multi_loss_base = val;
620                         multi_lagloss_dcf();
621                 }
622         }                       
623 }
624
625 DCF(loss_min, "")
626 {
627         // if the lag system isn't inited, don't do anything
628         if(!Multi_lag_inited){
629                 dc_printf("Lag System Not Initialized!\n");
630                 return;
631         }
632
633         // parse the argument and change things around accordingly
634         dc_get_arg(ARG_INT);
635         if(Dc_arg_type & ARG_INT){                      
636       float val = (float)Dc_arg_int / 100.0f;
637
638                 if(val > Multi_loss_base){
639                         dc_printf("Min value greater than base value, ignoring...");
640                 } else {
641                         // otherwise set the value
642                         if(Dc_arg_int < 0){
643                                 Multi_loss_min = -1.0f;
644                         } else {
645                                 Multi_loss_min = val;
646                         }
647                         multi_lagloss_dcf();
648                 }
649         }
650 }
651
652 DCF(loss_max, "")
653 {       
654         // if the lag system isn't inited, don't do anything
655         if(!Multi_lag_inited){
656                 dc_printf("Lag System Not Initialized!\n");
657                 return;
658         }
659
660         // parse the argument and change things around accordingly
661         dc_get_arg(ARG_INT);
662         if(Dc_arg_type & ARG_INT){                      
663       float val = (float)Dc_arg_int / 100.0f;
664
665                 if(val < Multi_loss_base){
666                         dc_printf("Max value smaller than base value, ignoring...");
667                 } else {
668                         // otherwise set the value
669                         if(Dc_arg_int < 0){
670                                 Multi_loss_max = -1.0f;
671                         } else {
672                                 Multi_loss_min = val;
673                         }
674                         multi_lagloss_dcf();
675                 }
676         }                       
677 }
678
679 DCF(lagloss, "")
680 {
681         // if the lag system isn't inited, don't do anything
682         if(!Multi_lag_inited){
683                 dc_printf("Lag System Not Initialized!\n");
684                 return;
685         }
686
687         multi_lagloss_dcf();
688 }
689
690 DCF(lag_streak, "")
691 {
692         // if the lag system isn't inited, don't do anything
693         if(!Multi_lag_inited){
694                 dc_printf("Lag System Not Initialized!\n");
695                 return;
696         }
697
698         dc_get_arg(ARG_INT);
699         if(Dc_arg_type & ARG_INT){                                      
700                 if(Dc_arg_int >= 0){
701                         Multi_streak_time = Dc_arg_int;
702                 } 
703         }
704 }
705
706 DCF(lag_bad, "")
707 {
708         // if the lag system isn't inited, don't do anything
709         if(!Multi_lag_inited){
710                 dc_printf("Lag System Not Initialized!\n");
711                 return;
712         }
713
714         dc_printf("Setting bad lag/loss parameters\n");
715
716         // set good lagloss parameters
717         Multi_lag_base = 500;
718         Multi_lag_min = 400;
719         Multi_lag_max = 600;
720         
721         Multi_loss_base = 0.2f;
722         Multi_loss_min = 0.15f;
723         Multi_loss_max = 0.23f;
724
725         Multi_streak_time = 800;
726         Multi_streak_stamp = -1;
727         Multi_current_streak = -1;
728 }
729
730 DCF(lag_avg, "")
731 {
732         // if the lag system isn't inited, don't do anything
733         if(!Multi_lag_inited){
734                 dc_printf("Lag System Not Initialized!\n");
735                 return;
736         }
737
738         dc_printf("Setting avg lag/loss parameters\n");
739
740         // set good lagloss parameters
741         Multi_lag_base = 275;
742         Multi_lag_min = 200;
743         Multi_lag_max = 400;
744         
745         Multi_loss_base = 0.15f;
746         Multi_loss_min = 0.1f;
747         Multi_loss_max = 0.20f;
748
749         Multi_streak_time = 900;
750         Multi_streak_stamp = -1;
751         Multi_current_streak = -1;
752 }
753
754 DCF(lag_good, "")
755 {
756         // if the lag system isn't inited, don't do anything
757         if(!Multi_lag_inited){
758                 dc_printf("Lag System Not Initialized!\n");
759                 return;
760         }
761
762         dc_printf("Setting good lag/loss parameters\n");
763
764         // set good lagloss parameters
765         Multi_lag_base = 100;
766         Multi_lag_min = 35;
767         Multi_lag_max = 200;
768         
769         Multi_loss_base = 0.08f;
770         Multi_loss_min = 0.0f;
771         Multi_loss_max = 0.1f;
772
773         Multi_streak_time = 1000;
774         Multi_streak_stamp = -1;
775         Multi_current_streak = -1;
776 }
777