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