]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multilag.cpp
make multilag work, if we ever want to use it
[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 <winsock.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;
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                 }
293                         
294                 // wacky socket error
295                 if(ret_val == SOCKET_ERROR){
296                         return SOCKET_ERROR;
297                 }
298
299                 // if we should be dropping this packet
300                 if(!multi_lag_should_be_lost()){
301                         // get a free packet buf and stuff the data
302                         item = multi_lag_get_free();
303                         if(item){
304                                 SDL_assert(ret_val < 700);
305                                 memcpy(item->data, t_buf, ret_val);                     
306                                 item->data_len = ret_val;
307                                 item->ip_addr = ip_addr;
308                                 item->socket = nfds;
309                                 item->stamp = timestamp(multi_lag_get_random_lag());
310                         }               
311                 }
312         }
313
314         // always unset the readfds
315         FD_CLR(nfds, readfds);
316
317         // now determine if we have any pending packets - find the first one
318         // NOTE : this _could_ be the packet we just read. In fact, with a 0 lag, this will always be the case
319         moveup=GET_FIRST(&Lag_used_list);
320         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
321                 // if the timestamp has elapsed and we have a matching socket
322                 if((nfds == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
323                         // set this so we think select returned yes
324                         FD_SET(nfds, readfds);
325                         return 1;
326                 }
327
328                 moveup = GET_NEXT(moveup);
329         }
330
331         // no data
332         return 0;
333 }
334
335 // recvfrom for multilag
336 int multi_lag_recvfrom(uint s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
337 {
338         lag_buf *moveup = NULL;
339         lag_buf *item = NULL;
340
341         // now determine if we have any pending packets - find the first one
342         moveup=GET_FIRST(&Lag_used_list);
343         while ( moveup!=END_OF_LIST(&Lag_used_list) )   {               
344                 // if the timestamp has elapsed
345                 if(((int)s == (SOCKET)moveup->socket) && ((moveup->stamp <= 0) || timestamp_elapsed(moveup->stamp))){
346                         item = moveup;
347                         break;
348                 }
349
350                 moveup = GET_NEXT(moveup);
351         }
352
353         // if this happens, it means that the multi_lag_select() returned an improper value
354         SDL_assert(item);
355         // stuff the data
356         SDL_assert(item->data_len <= len);
357         memcpy(buf, item->data, item->data_len);
358         if(Tcp_active){
359                 memcpy(from, &item->ip_addr, sizeof(struct sockaddr_in));
360         } else {
361                 Int3();
362         }
363
364         // stick the item back on the free list
365         multi_lag_put_free(item);
366
367         // return the size in bytes
368         return item->data_len;
369 }
370
371 // ----------------------------------------------------------------------------------------------------
372 // LAGLOSS FORWARD DEFINITIONS
373 //
374
375 int multi_lag_get_random_lag()
376 {
377         // first determine the percentage we'll be checking against
378         int ret;
379         int mod;        
380
381         // if the lag system isn't inited, don't do anything (no lag)
382         if(!Multi_lag_inited){
383                 return 0;
384         }
385                 
386         // pick a value
387         // see if we should be going up or down (loss max/loss min)
388         mod = 0;
389         if((float)myrand()/(float)MY_RAND_MAX < 0.5){
390                 // down
391                 if(Multi_lag_min >= 0){
392                         mod = - (int)((float)(Multi_lag_base - Multi_lag_min) * ((float)myrand()/(float)MY_RAND_MAX));
393                 }
394         } else {
395                 // up
396                 if(Multi_lag_max >= 0){
397                         mod = (int)((float)(Multi_lag_max - Multi_lag_base) * ((float)myrand()/(float)MY_RAND_MAX));
398                 }
399         }
400         
401         // if the current streak has elapsed, calculate a new one
402         if((Multi_streak_stamp == -1) || (timestamp_elapsed(Multi_streak_stamp))){
403                 // timestamp the new streak
404                 Multi_streak_stamp = timestamp(Multi_streak_time);
405
406                 // set the return value
407                 ret = Multi_lag_base + mod;
408                 
409                 // set the lag value of this current streak
410                 Multi_current_streak = ret;
411         } 
412         // otherwise use the lag for the current streak
413         else {
414                 ret = Multi_current_streak;
415         }
416                         
417         return ret;     
418 }
419
420 // this _may_ be a bit heavyweight, but it _is_ debug code
421 int multi_lag_should_be_lost()
422 {       
423         // first determine the percentage we'll be checking against
424         float mod;      
425
426         // if the lag system isn't inited, don't do anything
427         if(!Multi_lag_inited){
428                 return 0;
429         }
430                 
431         // see if we should be going up or down (loss max/loss min)
432         mod = 0.0f;
433         if((float)myrand()/(float)MY_RAND_MAX < 0.5){
434                 // down
435                 if(Multi_loss_min >= 0.0f){
436                         mod = - ((Multi_loss_base - Multi_loss_min) * ((float)myrand()/(float)MY_RAND_MAX));
437                 }
438         } else {
439                 // up
440                 if(Multi_loss_max >= 0.0f){
441                         mod = ((Multi_loss_max - Multi_loss_base) * ((float)myrand()/(float)MY_RAND_MAX));
442                 }
443         }       
444         
445         if((float)myrand()/(float)MY_RAND_MAX <= Multi_loss_base + mod){
446                 return 1;
447         }       
448
449         return 0;
450 }
451
452 // get a free packet buffer, return NULL on fail
453 lag_buf *multi_lag_get_free()
454 {
455         lag_buf *lagp;
456
457         // if we're out of buffers
458         if(Lag_buf_count >= MAX_LAG_BUFFERS){
459                 nprintf(("Network", "Out of lag buffers!\n"));
460                 return NULL;
461         }
462
463         // get a free item
464         lagp = GET_FIRST(&Lag_free_list);
465         SDL_assert( lagp != &Lag_free_list );           // shouldn't have the dummy element
466
467         // remove trailp from the free list
468         list_remove( &Lag_free_list, lagp );
469         
470         // insert trailp onto the end of used list
471         list_append( &Lag_used_list, lagp );
472
473         // increase the count
474         Lag_buf_count++;
475         return lagp;
476 }
477
478 // put a lag buffer back
479 void multi_lag_put_free(lag_buf *buf)
480 {
481         // remove objp from the used list
482         list_remove( &Lag_used_list, buf);
483
484         // add objp to the end of the free
485         list_append( &Lag_free_list, buf );
486
487         // decrement counter
488         Lag_buf_count--;
489 }
490
491 void multi_lagloss_dcf()
492 {
493         // if the lag system isn't inited, don't do anything
494         if(!Multi_lag_inited){
495                 dc_printf("Lag System Not Initialized!\n");
496                 return;
497         }
498
499         // display all available commands
500         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");
501
502         // display lag settings
503         dc_printf("Lag : ");            
504         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);       
505
506         // display loss settings
507         dc_printf("Loss : ");           
508         dc_printf("\n   Base %f\n   Min %f\n   Max %f\n", Multi_loss_base, Multi_loss_min, Multi_loss_max);     
509 }
510
511 DCF(lag, "")
512 {
513         // if the lag system isn't inited, don't do anything
514         if(!Multi_lag_inited){
515                 dc_printf("Lag System Not Initialized!\n");
516                 return;
517         }
518
519         dc_get_arg(ARG_INT);            
520         // parse the argument and change things around accordingly
521         if(Dc_arg_type & ARG_INT){                      
522                 if(Dc_arg_int < 0){
523                         // switch the lag sim off
524                         Multi_lag_base = -1;
525                         Multi_lag_min = -1;
526                         Multi_lag_max = -1;
527                         dc_printf("Turning simulated lag off\n");
528                         multi_lagloss_dcf();
529                 } else if((Multi_lag_max >= 0) && (Dc_arg_int > Multi_lag_max)){
530                         dc_printf("Base value greater than max value, ignoring...");
531                 } else if((Multi_lag_min >= 0) && (Dc_arg_int < Multi_lag_min)){
532                         dc_printf("Base value smaller than min value, ignoring...");
533                 } else {
534                         Multi_lag_base = Dc_arg_int;
535                         multi_lagloss_dcf();
536                 }
537         }       
538 }
539
540 DCF(lag_min, "")
541 {
542         // if the lag system isn't inited, don't do anything
543         if(!Multi_lag_inited){
544                 dc_printf("Lag System Not Initialized!\n");
545                 return;
546         }
547
548         dc_get_arg(ARG_INT);            
549         // parse the argument and change things around accordingly
550         if(Dc_arg_type & ARG_INT){                      
551                 if(Dc_arg_int > Multi_lag_base){
552                         dc_printf("Min value greater than base value, ignoring...");
553                 } else {
554                         if(Dc_arg_int < 0){
555                                 Multi_lag_min = -1;
556                         } else {
557                                 Multi_lag_min = Dc_arg_int;
558                         }
559                         multi_lagloss_dcf();
560                 }
561         }                       
562 }
563
564 DCF(lag_max, "")
565 {
566         // if the lag system isn't inited, don't do anything
567         if(!Multi_lag_inited){
568                 dc_printf("Lag System Not Initialized!\n");
569                 return;
570         }
571
572         // parse the argument and change things around accordingly
573         dc_get_arg(ARG_INT);
574         if(Dc_arg_type & ARG_INT){                      
575                 if((Dc_arg >=0) && (Dc_arg_int < Multi_lag_base)){
576                         dc_printf("Max value smaller than base value, ignoring...");
577                 } else {
578                         if(Dc_arg_int < 0){
579                                 Multi_lag_max = -1;
580                         } else {
581                                 Multi_lag_max = Dc_arg_int;
582                         }
583                         multi_lagloss_dcf();
584                 }
585         }               
586 }
587
588 DCF(loss, "")
589 {
590         // if the lag system isn't inited, don't do anything
591         if(!Multi_lag_inited){
592                 dc_printf("Lag System Not Initialized!\n");
593                 return;
594         }
595
596         // parse the argument and change things around accordingly
597         dc_get_arg(ARG_INT);
598         if(Dc_arg_type & ARG_INT){
599                 float val = (float)Dc_arg_int / 100.0f;
600                         
601                 if(Dc_arg_int > 100){
602                         dc_printf("Illegal loss base value, ignoring...");
603                 } else if(Dc_arg_int < 0){
604                         // switch the loss sim off
605                         dc_printf("Turning simulated loss off\n");
606                         Multi_loss_base = -1.0f;
607                         Multi_loss_min = -1.0f;
608                         Multi_loss_max = -1.0f;
609                         multi_lagloss_dcf();
610                 } else if((Multi_loss_max >= 0.0f) && (val > Multi_loss_max)){
611                         dc_printf("Base value greater than max value, ignoring...");
612                 } else if((Multi_loss_min >= 0.0f) && (val < Multi_loss_min)){
613                         dc_printf("Base value smaller than min value, ignoring...");
614                 } else {
615                         Multi_loss_base = val;
616                         multi_lagloss_dcf();
617                 }
618         }                       
619 }
620
621 DCF(loss_min, "")
622 {
623         // if the lag system isn't inited, don't do anything
624         if(!Multi_lag_inited){
625                 dc_printf("Lag System Not Initialized!\n");
626                 return;
627         }
628
629         // parse the argument and change things around accordingly
630         dc_get_arg(ARG_INT);
631         if(Dc_arg_type & ARG_INT){                      
632       float val = (float)Dc_arg_int / 100.0f;
633
634                 if(val > Multi_loss_base){
635                         dc_printf("Min value greater than base value, ignoring...");
636                 } else {
637                         // otherwise set the value
638                         if(Dc_arg_int < 0){
639                                 Multi_loss_min = -1.0f;
640                         } else {
641                                 Multi_loss_min = val;
642                         }
643                         multi_lagloss_dcf();
644                 }
645         }
646 }
647
648 DCF(loss_max, "")
649 {       
650         // if the lag system isn't inited, don't do anything
651         if(!Multi_lag_inited){
652                 dc_printf("Lag System Not Initialized!\n");
653                 return;
654         }
655
656         // parse the argument and change things around accordingly
657         dc_get_arg(ARG_INT);
658         if(Dc_arg_type & ARG_INT){                      
659       float val = (float)Dc_arg_int / 100.0f;
660
661                 if(val < Multi_loss_base){
662                         dc_printf("Max value smaller than base value, ignoring...");
663                 } else {
664                         // otherwise set the value
665                         if(Dc_arg_int < 0){
666                                 Multi_loss_max = -1.0f;
667                         } else {
668                                 Multi_loss_min = val;
669                         }
670                         multi_lagloss_dcf();
671                 }
672         }                       
673 }
674
675 DCF(lagloss, "")
676 {
677         // if the lag system isn't inited, don't do anything
678         if(!Multi_lag_inited){
679                 dc_printf("Lag System Not Initialized!\n");
680                 return;
681         }
682
683         multi_lagloss_dcf();
684 }
685
686 DCF(lag_streak, "")
687 {
688         // if the lag system isn't inited, don't do anything
689         if(!Multi_lag_inited){
690                 dc_printf("Lag System Not Initialized!\n");
691                 return;
692         }
693
694         dc_get_arg(ARG_INT);
695         if(Dc_arg_type & ARG_INT){                                      
696                 if(Dc_arg_int >= 0){
697                         Multi_streak_time = Dc_arg_int;
698                 } 
699         }
700 }
701
702 DCF(lag_bad, "")
703 {
704         // if the lag system isn't inited, don't do anything
705         if(!Multi_lag_inited){
706                 dc_printf("Lag System Not Initialized!\n");
707                 return;
708         }
709
710         dc_printf("Setting bad lag/loss parameters\n");
711
712         // set good lagloss parameters
713         Multi_lag_base = 500;
714         Multi_lag_min = 400;
715         Multi_lag_max = 600;
716         
717         Multi_loss_base = 0.2f;
718         Multi_loss_min = 0.15f;
719         Multi_loss_max = 0.23f;
720
721         Multi_streak_time = 800;
722         Multi_streak_stamp = -1;
723         Multi_current_streak = -1;
724 }
725
726 DCF(lag_avg, "")
727 {
728         // if the lag system isn't inited, don't do anything
729         if(!Multi_lag_inited){
730                 dc_printf("Lag System Not Initialized!\n");
731                 return;
732         }
733
734         dc_printf("Setting avg lag/loss parameters\n");
735
736         // set good lagloss parameters
737         Multi_lag_base = 275;
738         Multi_lag_min = 200;
739         Multi_lag_max = 400;
740         
741         Multi_loss_base = 0.15f;
742         Multi_loss_min = 0.1f;
743         Multi_loss_max = 0.20f;
744
745         Multi_streak_time = 900;
746         Multi_streak_stamp = -1;
747         Multi_current_streak = -1;
748 }
749
750 DCF(lag_good, "")
751 {
752         // if the lag system isn't inited, don't do anything
753         if(!Multi_lag_inited){
754                 dc_printf("Lag System Not Initialized!\n");
755                 return;
756         }
757
758         dc_printf("Setting good lag/loss parameters\n");
759
760         // set good lagloss parameters
761         Multi_lag_base = 100;
762         Multi_lag_min = 35;
763         Multi_lag_max = 200;
764         
765         Multi_loss_base = 0.08f;
766         Multi_loss_min = 0.0f;
767         Multi_loss_max = 0.1f;
768
769         Multi_streak_time = 1000;
770         Multi_streak_stamp = -1;
771         Multi_current_streak = -1;
772 }
773