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