Annotation of quake2/client/menu.c, revision 1.1.1.4

1.1.1.4 ! root        1: /*
        !             2: Copyright (C) 1997-2001 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
1.1       root       20: #include <ctype.h>
1.1.1.2   root       21: #ifdef _WIN32
1.1       root       22: #include <io.h>
1.1.1.2   root       23: #endif
1.1       root       24: #include "client.h"
                     25: #include "../client/qmenu.h"
1.1.1.2   root       26: 
1.1       root       27: static int     m_main_cursor;
1.1.1.2   root       28: 
1.1       root       29: #define NUM_CURSOR_FRAMES 15
1.1.1.2   root       30: 
1.1       root       31: static char *menu_in_sound             = "misc/menu1.wav";
                     32: static char *menu_move_sound   = "misc/menu2.wav";
                     33: static char *menu_out_sound            = "misc/menu3.wav";
1.1.1.2   root       34: 
1.1       root       35: void M_Menu_Main_f (void);
                     36:        void M_Menu_Game_f (void);
                     37:                void M_Menu_LoadGame_f (void);
                     38:                void M_Menu_SaveGame_f (void);
                     39:                void M_Menu_PlayerConfig_f (void);
1.1.1.2   root       40:                        void M_Menu_DownloadOptions_f (void);
1.1       root       41:                void M_Menu_Credits_f( void );
                     42:        void M_Menu_Multiplayer_f( void );
                     43:                void M_Menu_JoinServer_f (void);
                     44:                        void M_Menu_AddressBook_f( void );
                     45:                void M_Menu_StartServer_f (void);
                     46:                        void M_Menu_DMOptions_f (void);
                     47:        void M_Menu_Video_f (void);
                     48:        void M_Menu_Options_f (void);
                     49:                void M_Menu_Keys_f (void);
                     50:        void M_Menu_Quit_f (void);
                     51: 
                     52:        void M_Menu_Credits( void );
1.1.1.2   root       53: 
1.1       root       54: qboolean       m_entersound;           // play after drawing a frame, so caching
                     55:                                                                // won't disrupt the sound
1.1.1.2   root       56: 
1.1       root       57: void   (*m_drawfunc) (void);
                     58: const char *(*m_keyfunc) (int key);
1.1.1.2   root       59: 
1.1       root       60: //=============================================================================
                     61: /* Support Routines */
1.1.1.2   root       62: 
1.1       root       63: #define        MAX_MENU_DEPTH  8
1.1.1.2   root       64: 
                     65: 
1.1       root       66: typedef struct
                     67: {
                     68:        void    (*draw) (void);
                     69:        const char *(*key) (int k);
                     70: } menulayer_t;
1.1.1.2   root       71: 
1.1       root       72: menulayer_t    m_layers[MAX_MENU_DEPTH];
                     73: int            m_menudepth;
                     74: 
                     75: static void M_Banner( char *name )
                     76: {
                     77:        int w, h;
                     78: 
                     79:        re.DrawGetPicSize (&w, &h, name );
                     80:        re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
                     81: }
1.1.1.2   root       82: 
1.1       root       83: void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
                     84: {
                     85:        int             i;
                     86: 
                     87:        if (Cvar_VariableValue ("maxclients") == 1 
                     88:                && Com_ServerState ())
                     89:                Cvar_Set ("paused", "1");
1.1.1.2   root       90: 
1.1.1.3   root       91:        // if this menu is already present, drop back to that level
1.1       root       92:        // to avoid stacking menus by hotkeys
                     93:        for (i=0 ; i<m_menudepth ; i++)
                     94:                if (m_layers[i].draw == draw &&
                     95:                        m_layers[i].key == key)
                     96:                {
                     97:                        m_menudepth = i;
                     98:                }
1.1.1.2   root       99: 
1.1       root      100:        if (i == m_menudepth)
                    101:        {
                    102:                if (m_menudepth >= MAX_MENU_DEPTH)
                    103:                        Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
                    104:                m_layers[m_menudepth].draw = m_drawfunc;
                    105:                m_layers[m_menudepth].key = m_keyfunc;
                    106:                m_menudepth++;
                    107:        }
1.1.1.2   root      108: 
1.1       root      109:        m_drawfunc = draw;
                    110:        m_keyfunc = key;
1.1.1.2   root      111: 
1.1       root      112:        m_entersound = true;
1.1.1.2   root      113: 
1.1       root      114:        cls.key_dest = key_menu;
                    115: }
1.1.1.2   root      116: 
1.1       root      117: void M_ForceMenuOff (void)
                    118: {
                    119:        m_drawfunc = 0;
                    120:        m_keyfunc = 0;
                    121:        cls.key_dest = key_game;
                    122:        m_menudepth = 0;
                    123:        Key_ClearStates ();
                    124:        Cvar_Set ("paused", "0");
                    125: }
1.1.1.2   root      126: 
1.1       root      127: void M_PopMenu (void)
                    128: {
                    129:        S_StartLocalSound( menu_out_sound );
                    130:        if (m_menudepth < 1)
                    131:                Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
                    132:        m_menudepth--;
1.1.1.2   root      133: 
1.1       root      134:        m_drawfunc = m_layers[m_menudepth].draw;
                    135:        m_keyfunc = m_layers[m_menudepth].key;
1.1.1.2   root      136: 
1.1       root      137:        if (!m_menudepth)
                    138:                M_ForceMenuOff ();
                    139: }
1.1.1.2   root      140: 
                    141: 
1.1       root      142: const char *Default_MenuKey( menuframework_s *m, int key )
                    143: {
                    144:        const char *sound = NULL;
                    145:        menucommon_s *item;
1.1.1.2   root      146: 
1.1       root      147:        if ( m )
                    148:        {
                    149:                if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
                    150:                {
                    151:                        if ( item->type == MTYPE_FIELD )
                    152:                        {
                    153:                                if ( Field_Key( ( menufield_s * ) item, key ) )
                    154:                                        return NULL;
                    155:                        }
                    156:                }
                    157:        }
1.1.1.2   root      158: 
1.1       root      159:        switch ( key )
                    160:        {
                    161:        case K_ESCAPE:
                    162:                M_PopMenu();
                    163:                return menu_out_sound;
                    164:        case K_KP_UPARROW:
                    165:        case K_UPARROW:
                    166:                if ( m )
                    167:                {
                    168:                        m->cursor--;
                    169:                        Menu_AdjustCursor( m, -1 );
                    170:                        sound = menu_move_sound;
                    171:                }
                    172:                break;
                    173:        case K_TAB:
                    174:                if ( m )
                    175:                {
                    176:                        m->cursor++;
                    177:                        Menu_AdjustCursor( m, 1 );
                    178:                        sound = menu_move_sound;
                    179:                }
                    180:                break;
                    181:        case K_KP_DOWNARROW:
                    182:        case K_DOWNARROW:
                    183:                if ( m )
                    184:                {
                    185:                        m->cursor++;
                    186:                        Menu_AdjustCursor( m, 1 );
                    187:                        sound = menu_move_sound;
                    188:                }
                    189:                break;
                    190:        case K_KP_LEFTARROW:
                    191:        case K_LEFTARROW:
                    192:                if ( m )
                    193:                {
                    194:                        Menu_SlideItem( m, -1 );
                    195:                        sound = menu_move_sound;
                    196:                }
                    197:                break;
                    198:        case K_KP_RIGHTARROW:
                    199:        case K_RIGHTARROW:
                    200:                if ( m )
                    201:                {
                    202:                        Menu_SlideItem( m, 1 );
                    203:                        sound = menu_move_sound;
                    204:                }
                    205:                break;
                    206: 
                    207:        case K_MOUSE1:
                    208:        case K_MOUSE2:
                    209:        case K_MOUSE3:
                    210:        case K_JOY1:
                    211:        case K_JOY2:
                    212:        case K_JOY3:
                    213:        case K_JOY4:
                    214:        case K_AUX1:
                    215:        case K_AUX2:
                    216:        case K_AUX3:
                    217:        case K_AUX4:
                    218:        case K_AUX5:
                    219:        case K_AUX6:
                    220:        case K_AUX7:
                    221:        case K_AUX8:
                    222:        case K_AUX9:
                    223:        case K_AUX10:
                    224:        case K_AUX11:
                    225:        case K_AUX12:
                    226:        case K_AUX13:
                    227:        case K_AUX14:
                    228:        case K_AUX15:
                    229:        case K_AUX16:
                    230:        case K_AUX17:
                    231:        case K_AUX18:
                    232:        case K_AUX19:
                    233:        case K_AUX20:
                    234:        case K_AUX21:
                    235:        case K_AUX22:
                    236:        case K_AUX23:
                    237:        case K_AUX24:
                    238:        case K_AUX25:
                    239:        case K_AUX26:
                    240:        case K_AUX27:
                    241:        case K_AUX28:
                    242:        case K_AUX29:
                    243:        case K_AUX30:
                    244:        case K_AUX31:
                    245:        case K_AUX32:
                    246:                
                    247:        case K_KP_ENTER:
                    248:        case K_ENTER:
                    249:                if ( m )
                    250:                        Menu_SelectItem( m );
                    251:                sound = menu_move_sound;
                    252:                break;
                    253:        }
1.1.1.2   root      254: 
1.1       root      255:        return sound;
                    256: }
1.1.1.2   root      257: 
1.1       root      258: //=============================================================================
1.1.1.2   root      259: 
1.1       root      260: /*
                    261: ================
                    262: M_DrawCharacter
1.1.1.2   root      263: 
1.1       root      264: Draws one solid graphics character
                    265: cx and cy are in 320*240 coordinates, and will be centered on
                    266: higher res screens.
                    267: ================
                    268: */
                    269: void M_DrawCharacter (int cx, int cy, int num)
                    270: {
                    271:        re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
                    272: }
1.1.1.2   root      273: 
1.1       root      274: void M_Print (int cx, int cy, char *str)
                    275: {
                    276:        while (*str)
                    277:        {
                    278:                M_DrawCharacter (cx, cy, (*str)+128);
                    279:                str++;
                    280:                cx += 8;
                    281:        }
                    282: }
1.1.1.2   root      283: 
1.1       root      284: void M_PrintWhite (int cx, int cy, char *str)
                    285: {
                    286:        while (*str)
                    287:        {
                    288:                M_DrawCharacter (cx, cy, *str);
                    289:                str++;
                    290:                cx += 8;
                    291:        }
                    292: }
1.1.1.2   root      293: 
1.1       root      294: void M_DrawPic (int x, int y, char *pic)
                    295: {
                    296:        re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
                    297: }
1.1.1.2   root      298: 
                    299: 
1.1       root      300: /*
                    301: =============
                    302: M_DrawCursor
1.1.1.2   root      303: 
1.1       root      304: Draws an animating cursor with the point at
                    305: x,y.  The pic will extend to the left of x,
                    306: and both above and below y.
                    307: =============
                    308: */
                    309: void M_DrawCursor( int x, int y, int f )
                    310: {
                    311:        char    cursorname[80];
                    312:        static qboolean cached;
                    313: 
                    314:        if ( !cached )
                    315:        {
                    316:                int i;
                    317: 
                    318:                for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
                    319:                {
                    320:                        Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
                    321: 
                    322:                        re.RegisterPic( cursorname );
                    323:                }
                    324:                cached = true;
                    325:        }
1.1.1.2   root      326: 
1.1       root      327:        Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
                    328:        re.DrawPic( x, y, cursorname );
                    329: }
1.1.1.2   root      330: 
1.1       root      331: void M_DrawTextBox (int x, int y, int width, int lines)
                    332: {
                    333:        int             cx, cy;
                    334:        int             n;
1.1.1.2   root      335: 
1.1       root      336:        // draw left side
                    337:        cx = x;
                    338:        cy = y;
                    339:        M_DrawCharacter (cx, cy, 1);
                    340:        for (n = 0; n < lines; n++)
                    341:        {
                    342:                cy += 8;
                    343:                M_DrawCharacter (cx, cy, 4);
                    344:        }
                    345:        M_DrawCharacter (cx, cy+8, 7);
1.1.1.2   root      346: 
1.1       root      347:        // draw middle
                    348:        cx += 8;
                    349:        while (width > 0)
                    350:        {
                    351:                cy = y;
                    352:                M_DrawCharacter (cx, cy, 2);
                    353:                for (n = 0; n < lines; n++)
                    354:                {
                    355:                        cy += 8;
                    356:                        M_DrawCharacter (cx, cy, 5);
                    357:                }
                    358:                M_DrawCharacter (cx, cy+8, 8);
                    359:                width -= 1;
                    360:                cx += 8;
                    361:        }
1.1.1.2   root      362: 
1.1       root      363:        // draw right side
                    364:        cy = y;
                    365:        M_DrawCharacter (cx, cy, 3);
                    366:        for (n = 0; n < lines; n++)
                    367:        {
                    368:                cy += 8;
                    369:                M_DrawCharacter (cx, cy, 6);
                    370:        }
                    371:        M_DrawCharacter (cx, cy+8, 9);
                    372: }
1.1.1.2   root      373: 
1.1       root      374:                
                    375: /*
                    376: =======================================================================
1.1.1.2   root      377: 
1.1       root      378: MAIN MENU
1.1.1.2   root      379: 
1.1       root      380: =======================================================================
                    381: */
                    382: #define        MAIN_ITEMS      5
1.1.1.2   root      383: 
                    384: 
1.1       root      385: void M_Main_Draw (void)
                    386: {
                    387:        int i;
                    388:        int w, h;
                    389:        int ystart;
                    390:        int     xoffset;
                    391:        int widest = -1;
                    392:        int totalheight = 0;
                    393:        char litname[80];
                    394:        char *names[] =
                    395:        {
                    396:                "m_main_game",
                    397:                "m_main_multiplayer",
                    398:                "m_main_options",
                    399:                "m_main_video",
                    400:                "m_main_quit",
                    401:                0
                    402:        };
1.1.1.2   root      403: 
1.1       root      404:        for ( i = 0; names[i] != 0; i++ )
                    405:        {
                    406:                re.DrawGetPicSize( &w, &h, names[i] );
1.1.1.2   root      407: 
1.1       root      408:                if ( w > widest )
                    409:                        widest = w;
                    410:                totalheight += ( h + 12 );
                    411:        }
                    412: 
                    413:        ystart = ( viddef.height / 2 - 110 );
                    414:        xoffset = ( viddef.width - widest + 70 ) / 2;
1.1.1.2   root      415: 
1.1       root      416:        for ( i = 0; names[i] != 0; i++ )
                    417:        {
                    418:                if ( i != m_main_cursor )
                    419:                        re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
                    420:        }
                    421:        strcpy( litname, names[m_main_cursor] );
                    422:        strcat( litname, "_sel" );
                    423:        re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
1.1.1.2   root      424: 
1.1       root      425:        M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
1.1.1.2   root      426: 
1.1       root      427:        re.DrawGetPicSize( &w, &h, "m_main_plaque" );
                    428:        re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
1.1.1.2   root      429: 
1.1       root      430:        re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
                    431: }
1.1.1.2   root      432: 
                    433: 
1.1       root      434: const char *M_Main_Key (int key)
                    435: {
                    436:        const char *sound = menu_move_sound;
1.1.1.2   root      437: 
1.1       root      438:        switch (key)
                    439:        {
                    440:        case K_ESCAPE:
                    441:                M_PopMenu ();
                    442:                break;
                    443: 
                    444:        case K_KP_DOWNARROW:
                    445:        case K_DOWNARROW:
                    446:                if (++m_main_cursor >= MAIN_ITEMS)
                    447:                        m_main_cursor = 0;
                    448:                return sound;
1.1.1.2   root      449: 
1.1       root      450:        case K_KP_UPARROW:
                    451:        case K_UPARROW:
                    452:                if (--m_main_cursor < 0)
                    453:                        m_main_cursor = MAIN_ITEMS - 1;
                    454:                return sound;
                    455: 
                    456:        case K_KP_ENTER:
                    457:        case K_ENTER:
                    458:                m_entersound = true;
1.1.1.2   root      459: 
1.1       root      460:                switch (m_main_cursor)
                    461:                {
                    462:                case 0:
                    463:                        M_Menu_Game_f ();
                    464:                        break;
1.1.1.2   root      465: 
1.1       root      466:                case 1:
                    467:                        M_Menu_Multiplayer_f();
                    468:                        break;
1.1.1.2   root      469: 
1.1       root      470:                case 2:
                    471:                        M_Menu_Options_f ();
                    472:                        break;
1.1.1.2   root      473: 
1.1       root      474:                case 3:
                    475:                        M_Menu_Video_f ();
                    476:                        break;
1.1.1.2   root      477: 
1.1       root      478:                case 4:
                    479:                        M_Menu_Quit_f ();
                    480:                        break;
                    481:                }
                    482:        }
1.1.1.2   root      483: 
1.1       root      484:        return NULL;
                    485: }
1.1.1.2   root      486: 
                    487: 
1.1       root      488: void M_Menu_Main_f (void)
                    489: {
                    490:        M_PushMenu (M_Main_Draw, M_Main_Key);
                    491: }
                    492: 
                    493: /*
                    494: =======================================================================
                    495: 
                    496: MULTIPLAYER MENU
                    497: 
                    498: =======================================================================
                    499: */
                    500: static menuframework_s s_multiplayer_menu;
                    501: static menuaction_s            s_join_network_server_action;
                    502: static menuaction_s            s_start_network_server_action;
                    503: static menuaction_s            s_player_setup_action;
                    504: 
                    505: static void Multiplayer_MenuDraw (void)
                    506: {
                    507:        M_Banner( "m_banner_multiplayer" );
                    508: 
                    509:        Menu_AdjustCursor( &s_multiplayer_menu, 1 );
                    510:        Menu_Draw( &s_multiplayer_menu );
                    511: }
                    512: 
                    513: static void PlayerSetupFunc( void *unused )
                    514: {
                    515:        M_Menu_PlayerConfig_f();
                    516: }
                    517: 
                    518: static void JoinNetworkServerFunc( void *unused )
                    519: {
                    520:        M_Menu_JoinServer_f();
                    521: }
                    522: 
                    523: static void StartNetworkServerFunc( void *unused )
                    524: {
                    525:        M_Menu_StartServer_f ();
                    526: }
                    527: 
                    528: void Multiplayer_MenuInit( void )
                    529: {
                    530:        s_multiplayer_menu.x = viddef.width * 0.50 - 64;
                    531:        s_multiplayer_menu.nitems = 0;
                    532: 
                    533:        s_join_network_server_action.generic.type       = MTYPE_ACTION;
                    534:        s_join_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    535:        s_join_network_server_action.generic.x          = 0;
                    536:        s_join_network_server_action.generic.y          = 0;
                    537:        s_join_network_server_action.generic.name       = " join network server";
                    538:        s_join_network_server_action.generic.callback = JoinNetworkServerFunc;
                    539: 
                    540:        s_start_network_server_action.generic.type      = MTYPE_ACTION;
                    541:        s_start_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    542:        s_start_network_server_action.generic.x         = 0;
                    543:        s_start_network_server_action.generic.y         = 10;
                    544:        s_start_network_server_action.generic.name      = " start network server";
                    545:        s_start_network_server_action.generic.callback = StartNetworkServerFunc;
                    546: 
                    547:        s_player_setup_action.generic.type      = MTYPE_ACTION;
                    548:        s_player_setup_action.generic.flags  = QMF_LEFT_JUSTIFY;
                    549:        s_player_setup_action.generic.x         = 0;
                    550:        s_player_setup_action.generic.y         = 20;
                    551:        s_player_setup_action.generic.name      = " player setup";
                    552:        s_player_setup_action.generic.callback = PlayerSetupFunc;
                    553: 
                    554:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_join_network_server_action );
                    555:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_start_network_server_action );
                    556:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_player_setup_action );
                    557: 
1.1.1.2   root      558:        Menu_SetStatusBar( &s_multiplayer_menu, NULL );
                    559: 
1.1       root      560:        Menu_Center( &s_multiplayer_menu );
                    561: }
                    562: 
                    563: const char *Multiplayer_MenuKey( int key )
                    564: {
                    565:        return Default_MenuKey( &s_multiplayer_menu, key );
                    566: }
                    567: 
                    568: void M_Menu_Multiplayer_f( void )
                    569: {
                    570:        Multiplayer_MenuInit();
                    571:        M_PushMenu( Multiplayer_MenuDraw, Multiplayer_MenuKey );
                    572: }
1.1.1.2   root      573: 
1.1       root      574: /*
                    575: =======================================================================
                    576: 
                    577: KEYS MENU
                    578: 
                    579: =======================================================================
                    580: */
                    581: char *bindnames[][2] =
                    582: {
                    583: {"+attack",            "attack"},
                    584: {"weapnext",           "next weapon"},
                    585: {"+forward",           "walk forward"},
                    586: {"+back",                      "backpedal"},
                    587: {"+left",                      "turn left"},
                    588: {"+right",                     "turn right"},
                    589: {"+speed",                     "run"},
                    590: {"+moveleft",          "step left"},
                    591: {"+moveright",                 "step right"},
                    592: {"+strafe",            "sidestep"},
                    593: {"+lookup",            "look up"},
                    594: {"+lookdown",          "look down"},
                    595: {"centerview",                 "center view"},
                    596: {"+mlook",                     "mouse look"},
                    597: {"+klook",                     "keyboard look"},
                    598: {"+moveup",                    "up / jump"},
                    599: {"+movedown",          "down / crouch"},
1.1.1.2   root      600: 
1.1       root      601: {"inven",                      "inventory"},
                    602: {"invuse",                     "use item"},
                    603: {"invdrop",                    "drop item"},
                    604: {"invprev",                    "prev item"},
                    605: {"invnext",                    "next item"},
1.1.1.2   root      606: 
1.1       root      607: {"cmd help",           "help computer" }, 
                    608: { 0, 0 }
                    609: };
1.1.1.2   root      610: 
1.1       root      611: int                            keys_cursor;
                    612: static int             bind_grab;
1.1.1.2   root      613: 
1.1       root      614: static menuframework_s s_keys_menu;
                    615: static menuaction_s            s_keys_attack_action;
                    616: static menuaction_s            s_keys_change_weapon_action;
                    617: static menuaction_s            s_keys_walk_forward_action;
                    618: static menuaction_s            s_keys_backpedal_action;
                    619: static menuaction_s            s_keys_turn_left_action;
                    620: static menuaction_s            s_keys_turn_right_action;
                    621: static menuaction_s            s_keys_run_action;
                    622: static menuaction_s            s_keys_step_left_action;
                    623: static menuaction_s            s_keys_step_right_action;
                    624: static menuaction_s            s_keys_sidestep_action;
                    625: static menuaction_s            s_keys_look_up_action;
                    626: static menuaction_s            s_keys_look_down_action;
                    627: static menuaction_s            s_keys_center_view_action;
                    628: static menuaction_s            s_keys_mouse_look_action;
                    629: static menuaction_s            s_keys_keyboard_look_action;
                    630: static menuaction_s            s_keys_move_up_action;
                    631: static menuaction_s            s_keys_move_down_action;
                    632: static menuaction_s            s_keys_inventory_action;
                    633: static menuaction_s            s_keys_inv_use_action;
                    634: static menuaction_s            s_keys_inv_drop_action;
                    635: static menuaction_s            s_keys_inv_prev_action;
                    636: static menuaction_s            s_keys_inv_next_action;
1.1.1.2   root      637: 
1.1       root      638: static menuaction_s            s_keys_help_computer_action;
1.1.1.2   root      639: 
1.1       root      640: static void M_UnbindCommand (char *command)
                    641: {
                    642:        int             j;
                    643:        int             l;
                    644:        char    *b;
1.1.1.2   root      645: 
1.1       root      646:        l = strlen(command);
1.1.1.2   root      647: 
1.1       root      648:        for (j=0 ; j<256 ; j++)
                    649:        {
                    650:                b = keybindings[j];
                    651:                if (!b)
                    652:                        continue;
                    653:                if (!strncmp (b, command, l) )
                    654:                        Key_SetBinding (j, "");
                    655:        }
                    656: }
1.1.1.2   root      657: 
1.1       root      658: static void M_FindKeysForCommand (char *command, int *twokeys)
                    659: {
                    660:        int             count;
                    661:        int             j;
                    662:        int             l;
                    663:        char    *b;
1.1.1.2   root      664: 
1.1       root      665:        twokeys[0] = twokeys[1] = -1;
                    666:        l = strlen(command);
                    667:        count = 0;
1.1.1.2   root      668: 
1.1       root      669:        for (j=0 ; j<256 ; j++)
                    670:        {
                    671:                b = keybindings[j];
                    672:                if (!b)
                    673:                        continue;
                    674:                if (!strncmp (b, command, l) )
                    675:                {
                    676:                        twokeys[count] = j;
                    677:                        count++;
                    678:                        if (count == 2)
                    679:                                break;
                    680:                }
                    681:        }
                    682: }
1.1.1.2   root      683: 
1.1       root      684: static void KeyCursorDrawFunc( menuframework_s *menu )
                    685: {
                    686:        if ( bind_grab )
                    687:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, '=' );
                    688:        else
                    689:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, 12 + ( ( int ) ( Sys_Milliseconds() / 250 ) & 1 ) );
                    690: }
1.1.1.2   root      691: 
1.1       root      692: static void DrawKeyBindingFunc( void *self )
                    693: {
                    694:        int keys[2];
                    695:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root      696: 
1.1       root      697:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys);
                    698:                
                    699:        if (keys[0] == -1)
                    700:        {
                    701:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, "???" );
                    702:        }
                    703:        else
                    704:        {
                    705:                int x;
                    706:                const char *name;
1.1.1.2   root      707: 
1.1       root      708:                name = Key_KeynumToString (keys[0]);
1.1.1.2   root      709: 
1.1       root      710:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, name );
1.1.1.2   root      711: 
1.1       root      712:                x = strlen(name) * 8;
1.1.1.2   root      713: 
1.1       root      714:                if (keys[1] != -1)
                    715:                {
                    716:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 24 + x, a->generic.y + a->generic.parent->y, "or" );
                    717:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 48 + x, a->generic.y + a->generic.parent->y, Key_KeynumToString (keys[1]) );
                    718:                }
                    719:        }
                    720: }
1.1.1.2   root      721: 
1.1       root      722: static void KeyBindingFunc( void *self )
                    723: {
                    724:        menuaction_s *a = ( menuaction_s * ) self;
                    725:        int keys[2];
1.1.1.2   root      726: 
1.1       root      727:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys );
1.1.1.2   root      728: 
1.1       root      729:        if (keys[1] != -1)
                    730:                M_UnbindCommand( bindnames[a->generic.localdata[0]][0]);
1.1.1.2   root      731: 
1.1       root      732:        bind_grab = true;
1.1.1.2   root      733: 
1.1       root      734:        Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
                    735: }
1.1.1.2   root      736: 
1.1       root      737: static void Keys_MenuInit( void )
                    738: {
                    739:        int y = 0;
                    740:        int i = 0;
1.1.1.2   root      741: 
1.1       root      742:        s_keys_menu.x = viddef.width * 0.50;
                    743:        s_keys_menu.nitems = 0;
                    744:        s_keys_menu.cursordraw = KeyCursorDrawFunc;
1.1.1.2   root      745: 
1.1       root      746:        s_keys_attack_action.generic.type       = MTYPE_ACTION;
                    747:        s_keys_attack_action.generic.flags  = QMF_GRAYED;
                    748:        s_keys_attack_action.generic.x          = 0;
                    749:        s_keys_attack_action.generic.y          = y;
                    750:        s_keys_attack_action.generic.ownerdraw = DrawKeyBindingFunc;
                    751:        s_keys_attack_action.generic.localdata[0] = i;
                    752:        s_keys_attack_action.generic.name       = bindnames[s_keys_attack_action.generic.localdata[0]][1];
1.1.1.2   root      753: 
1.1       root      754:        s_keys_change_weapon_action.generic.type        = MTYPE_ACTION;
                    755:        s_keys_change_weapon_action.generic.flags  = QMF_GRAYED;
                    756:        s_keys_change_weapon_action.generic.x           = 0;
                    757:        s_keys_change_weapon_action.generic.y           = y += 9;
                    758:        s_keys_change_weapon_action.generic.ownerdraw = DrawKeyBindingFunc;
                    759:        s_keys_change_weapon_action.generic.localdata[0] = ++i;
                    760:        s_keys_change_weapon_action.generic.name        = bindnames[s_keys_change_weapon_action.generic.localdata[0]][1];
1.1.1.2   root      761: 
1.1       root      762:        s_keys_walk_forward_action.generic.type = MTYPE_ACTION;
                    763:        s_keys_walk_forward_action.generic.flags  = QMF_GRAYED;
                    764:        s_keys_walk_forward_action.generic.x            = 0;
                    765:        s_keys_walk_forward_action.generic.y            = y += 9;
                    766:        s_keys_walk_forward_action.generic.ownerdraw = DrawKeyBindingFunc;
                    767:        s_keys_walk_forward_action.generic.localdata[0] = ++i;
                    768:        s_keys_walk_forward_action.generic.name = bindnames[s_keys_walk_forward_action.generic.localdata[0]][1];
1.1.1.2   root      769: 
1.1       root      770:        s_keys_backpedal_action.generic.type    = MTYPE_ACTION;
                    771:        s_keys_backpedal_action.generic.flags  = QMF_GRAYED;
                    772:        s_keys_backpedal_action.generic.x               = 0;
                    773:        s_keys_backpedal_action.generic.y               = y += 9;
                    774:        s_keys_backpedal_action.generic.ownerdraw = DrawKeyBindingFunc;
                    775:        s_keys_backpedal_action.generic.localdata[0] = ++i;
                    776:        s_keys_backpedal_action.generic.name    = bindnames[s_keys_backpedal_action.generic.localdata[0]][1];
1.1.1.2   root      777: 
1.1       root      778:        s_keys_turn_left_action.generic.type    = MTYPE_ACTION;
                    779:        s_keys_turn_left_action.generic.flags  = QMF_GRAYED;
                    780:        s_keys_turn_left_action.generic.x               = 0;
                    781:        s_keys_turn_left_action.generic.y               = y += 9;
                    782:        s_keys_turn_left_action.generic.ownerdraw = DrawKeyBindingFunc;
                    783:        s_keys_turn_left_action.generic.localdata[0] = ++i;
                    784:        s_keys_turn_left_action.generic.name    = bindnames[s_keys_turn_left_action.generic.localdata[0]][1];
1.1.1.2   root      785: 
1.1       root      786:        s_keys_turn_right_action.generic.type   = MTYPE_ACTION;
                    787:        s_keys_turn_right_action.generic.flags  = QMF_GRAYED;
                    788:        s_keys_turn_right_action.generic.x              = 0;
                    789:        s_keys_turn_right_action.generic.y              = y += 9;
                    790:        s_keys_turn_right_action.generic.ownerdraw = DrawKeyBindingFunc;
                    791:        s_keys_turn_right_action.generic.localdata[0] = ++i;
                    792:        s_keys_turn_right_action.generic.name   = bindnames[s_keys_turn_right_action.generic.localdata[0]][1];
1.1.1.2   root      793: 
1.1       root      794:        s_keys_run_action.generic.type  = MTYPE_ACTION;
                    795:        s_keys_run_action.generic.flags  = QMF_GRAYED;
                    796:        s_keys_run_action.generic.x             = 0;
                    797:        s_keys_run_action.generic.y             = y += 9;
                    798:        s_keys_run_action.generic.ownerdraw = DrawKeyBindingFunc;
                    799:        s_keys_run_action.generic.localdata[0] = ++i;
                    800:        s_keys_run_action.generic.name  = bindnames[s_keys_run_action.generic.localdata[0]][1];
1.1.1.2   root      801: 
1.1       root      802:        s_keys_step_left_action.generic.type    = MTYPE_ACTION;
                    803:        s_keys_step_left_action.generic.flags  = QMF_GRAYED;
                    804:        s_keys_step_left_action.generic.x               = 0;
                    805:        s_keys_step_left_action.generic.y               = y += 9;
                    806:        s_keys_step_left_action.generic.ownerdraw = DrawKeyBindingFunc;
                    807:        s_keys_step_left_action.generic.localdata[0] = ++i;
                    808:        s_keys_step_left_action.generic.name    = bindnames[s_keys_step_left_action.generic.localdata[0]][1];
1.1.1.2   root      809: 
1.1       root      810:        s_keys_step_right_action.generic.type   = MTYPE_ACTION;
                    811:        s_keys_step_right_action.generic.flags  = QMF_GRAYED;
                    812:        s_keys_step_right_action.generic.x              = 0;
                    813:        s_keys_step_right_action.generic.y              = y += 9;
                    814:        s_keys_step_right_action.generic.ownerdraw = DrawKeyBindingFunc;
                    815:        s_keys_step_right_action.generic.localdata[0] = ++i;
                    816:        s_keys_step_right_action.generic.name   = bindnames[s_keys_step_right_action.generic.localdata[0]][1];
1.1.1.2   root      817: 
1.1       root      818:        s_keys_sidestep_action.generic.type     = MTYPE_ACTION;
                    819:        s_keys_sidestep_action.generic.flags  = QMF_GRAYED;
                    820:        s_keys_sidestep_action.generic.x                = 0;
                    821:        s_keys_sidestep_action.generic.y                = y += 9;
                    822:        s_keys_sidestep_action.generic.ownerdraw = DrawKeyBindingFunc;
                    823:        s_keys_sidestep_action.generic.localdata[0] = ++i;
                    824:        s_keys_sidestep_action.generic.name     = bindnames[s_keys_sidestep_action.generic.localdata[0]][1];
1.1.1.2   root      825: 
1.1       root      826:        s_keys_look_up_action.generic.type      = MTYPE_ACTION;
                    827:        s_keys_look_up_action.generic.flags  = QMF_GRAYED;
                    828:        s_keys_look_up_action.generic.x         = 0;
                    829:        s_keys_look_up_action.generic.y         = y += 9;
                    830:        s_keys_look_up_action.generic.ownerdraw = DrawKeyBindingFunc;
                    831:        s_keys_look_up_action.generic.localdata[0] = ++i;
                    832:        s_keys_look_up_action.generic.name      = bindnames[s_keys_look_up_action.generic.localdata[0]][1];
1.1.1.2   root      833: 
1.1       root      834:        s_keys_look_down_action.generic.type    = MTYPE_ACTION;
                    835:        s_keys_look_down_action.generic.flags  = QMF_GRAYED;
                    836:        s_keys_look_down_action.generic.x               = 0;
                    837:        s_keys_look_down_action.generic.y               = y += 9;
                    838:        s_keys_look_down_action.generic.ownerdraw = DrawKeyBindingFunc;
                    839:        s_keys_look_down_action.generic.localdata[0] = ++i;
                    840:        s_keys_look_down_action.generic.name    = bindnames[s_keys_look_down_action.generic.localdata[0]][1];
1.1.1.2   root      841: 
1.1       root      842:        s_keys_center_view_action.generic.type  = MTYPE_ACTION;
                    843:        s_keys_center_view_action.generic.flags  = QMF_GRAYED;
                    844:        s_keys_center_view_action.generic.x             = 0;
                    845:        s_keys_center_view_action.generic.y             = y += 9;
                    846:        s_keys_center_view_action.generic.ownerdraw = DrawKeyBindingFunc;
                    847:        s_keys_center_view_action.generic.localdata[0] = ++i;
                    848:        s_keys_center_view_action.generic.name  = bindnames[s_keys_center_view_action.generic.localdata[0]][1];
1.1.1.2   root      849: 
1.1       root      850:        s_keys_mouse_look_action.generic.type   = MTYPE_ACTION;
                    851:        s_keys_mouse_look_action.generic.flags  = QMF_GRAYED;
                    852:        s_keys_mouse_look_action.generic.x              = 0;
                    853:        s_keys_mouse_look_action.generic.y              = y += 9;
                    854:        s_keys_mouse_look_action.generic.ownerdraw = DrawKeyBindingFunc;
                    855:        s_keys_mouse_look_action.generic.localdata[0] = ++i;
                    856:        s_keys_mouse_look_action.generic.name   = bindnames[s_keys_mouse_look_action.generic.localdata[0]][1];
1.1.1.2   root      857: 
1.1       root      858:        s_keys_keyboard_look_action.generic.type        = MTYPE_ACTION;
                    859:        s_keys_keyboard_look_action.generic.flags  = QMF_GRAYED;
                    860:        s_keys_keyboard_look_action.generic.x           = 0;
                    861:        s_keys_keyboard_look_action.generic.y           = y += 9;
                    862:        s_keys_keyboard_look_action.generic.ownerdraw = DrawKeyBindingFunc;
                    863:        s_keys_keyboard_look_action.generic.localdata[0] = ++i;
                    864:        s_keys_keyboard_look_action.generic.name        = bindnames[s_keys_keyboard_look_action.generic.localdata[0]][1];
1.1.1.2   root      865: 
1.1       root      866:        s_keys_move_up_action.generic.type      = MTYPE_ACTION;
                    867:        s_keys_move_up_action.generic.flags  = QMF_GRAYED;
                    868:        s_keys_move_up_action.generic.x         = 0;
                    869:        s_keys_move_up_action.generic.y         = y += 9;
                    870:        s_keys_move_up_action.generic.ownerdraw = DrawKeyBindingFunc;
                    871:        s_keys_move_up_action.generic.localdata[0] = ++i;
                    872:        s_keys_move_up_action.generic.name      = bindnames[s_keys_move_up_action.generic.localdata[0]][1];
1.1.1.2   root      873: 
1.1       root      874:        s_keys_move_down_action.generic.type    = MTYPE_ACTION;
                    875:        s_keys_move_down_action.generic.flags  = QMF_GRAYED;
                    876:        s_keys_move_down_action.generic.x               = 0;
                    877:        s_keys_move_down_action.generic.y               = y += 9;
                    878:        s_keys_move_down_action.generic.ownerdraw = DrawKeyBindingFunc;
                    879:        s_keys_move_down_action.generic.localdata[0] = ++i;
                    880:        s_keys_move_down_action.generic.name    = bindnames[s_keys_move_down_action.generic.localdata[0]][1];
1.1.1.2   root      881: 
1.1       root      882:        s_keys_inventory_action.generic.type    = MTYPE_ACTION;
                    883:        s_keys_inventory_action.generic.flags  = QMF_GRAYED;
                    884:        s_keys_inventory_action.generic.x               = 0;
                    885:        s_keys_inventory_action.generic.y               = y += 9;
                    886:        s_keys_inventory_action.generic.ownerdraw = DrawKeyBindingFunc;
                    887:        s_keys_inventory_action.generic.localdata[0] = ++i;
                    888:        s_keys_inventory_action.generic.name    = bindnames[s_keys_inventory_action.generic.localdata[0]][1];
1.1.1.2   root      889: 
1.1       root      890:        s_keys_inv_use_action.generic.type      = MTYPE_ACTION;
                    891:        s_keys_inv_use_action.generic.flags  = QMF_GRAYED;
                    892:        s_keys_inv_use_action.generic.x         = 0;
                    893:        s_keys_inv_use_action.generic.y         = y += 9;
                    894:        s_keys_inv_use_action.generic.ownerdraw = DrawKeyBindingFunc;
                    895:        s_keys_inv_use_action.generic.localdata[0] = ++i;
                    896:        s_keys_inv_use_action.generic.name      = bindnames[s_keys_inv_use_action.generic.localdata[0]][1];
1.1.1.2   root      897: 
1.1       root      898:        s_keys_inv_drop_action.generic.type     = MTYPE_ACTION;
                    899:        s_keys_inv_drop_action.generic.flags  = QMF_GRAYED;
                    900:        s_keys_inv_drop_action.generic.x                = 0;
                    901:        s_keys_inv_drop_action.generic.y                = y += 9;
                    902:        s_keys_inv_drop_action.generic.ownerdraw = DrawKeyBindingFunc;
                    903:        s_keys_inv_drop_action.generic.localdata[0] = ++i;
                    904:        s_keys_inv_drop_action.generic.name     = bindnames[s_keys_inv_drop_action.generic.localdata[0]][1];
1.1.1.2   root      905: 
1.1       root      906:        s_keys_inv_prev_action.generic.type     = MTYPE_ACTION;
                    907:        s_keys_inv_prev_action.generic.flags  = QMF_GRAYED;
                    908:        s_keys_inv_prev_action.generic.x                = 0;
                    909:        s_keys_inv_prev_action.generic.y                = y += 9;
                    910:        s_keys_inv_prev_action.generic.ownerdraw = DrawKeyBindingFunc;
                    911:        s_keys_inv_prev_action.generic.localdata[0] = ++i;
                    912:        s_keys_inv_prev_action.generic.name     = bindnames[s_keys_inv_prev_action.generic.localdata[0]][1];
1.1.1.2   root      913: 
1.1       root      914:        s_keys_inv_next_action.generic.type     = MTYPE_ACTION;
                    915:        s_keys_inv_next_action.generic.flags  = QMF_GRAYED;
                    916:        s_keys_inv_next_action.generic.x                = 0;
                    917:        s_keys_inv_next_action.generic.y                = y += 9;
                    918:        s_keys_inv_next_action.generic.ownerdraw = DrawKeyBindingFunc;
                    919:        s_keys_inv_next_action.generic.localdata[0] = ++i;
                    920:        s_keys_inv_next_action.generic.name     = bindnames[s_keys_inv_next_action.generic.localdata[0]][1];
1.1.1.2   root      921: 
1.1       root      922:        s_keys_help_computer_action.generic.type        = MTYPE_ACTION;
                    923:        s_keys_help_computer_action.generic.flags  = QMF_GRAYED;
                    924:        s_keys_help_computer_action.generic.x           = 0;
                    925:        s_keys_help_computer_action.generic.y           = y += 9;
                    926:        s_keys_help_computer_action.generic.ownerdraw = DrawKeyBindingFunc;
                    927:        s_keys_help_computer_action.generic.localdata[0] = ++i;
                    928:        s_keys_help_computer_action.generic.name        = bindnames[s_keys_help_computer_action.generic.localdata[0]][1];
1.1.1.2   root      929: 
1.1       root      930:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_attack_action );
                    931:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_change_weapon_action );
                    932:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_walk_forward_action );
                    933:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_backpedal_action );
                    934:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_left_action );
                    935:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_right_action );
                    936:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_run_action );
                    937:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_left_action );
                    938:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_right_action );
                    939:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_sidestep_action );
                    940:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_up_action );
                    941:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_down_action );
                    942:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_center_view_action );
                    943:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_mouse_look_action );
                    944:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_keyboard_look_action );
                    945:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_up_action );
                    946:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_down_action );
1.1.1.2   root      947: 
1.1       root      948:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inventory_action );
                    949:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_use_action );
                    950:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_drop_action );
                    951:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_prev_action );
                    952:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_next_action );
1.1.1.2   root      953: 
1.1       root      954:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_help_computer_action );
                    955:        
                    956:        Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
                    957:        Menu_Center( &s_keys_menu );
                    958: }
1.1.1.2   root      959: 
1.1       root      960: static void Keys_MenuDraw (void)
                    961: {
                    962:        Menu_AdjustCursor( &s_keys_menu, 1 );
                    963:        Menu_Draw( &s_keys_menu );
                    964: }
1.1.1.2   root      965: 
1.1       root      966: static const char *Keys_MenuKey( int key )
                    967: {
                    968:        menuaction_s *item = ( menuaction_s * ) Menu_ItemAtCursor( &s_keys_menu );
1.1.1.2   root      969: 
1.1       root      970:        if ( bind_grab )
                    971:        {       
                    972:                if ( key != K_ESCAPE && key != '`' )
                    973:                {
                    974:                        char cmd[1024];
1.1.1.2   root      975: 
1.1       root      976:                        Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item->generic.localdata[0]][0]);
                    977:                        Cbuf_InsertText (cmd);
                    978:                }
                    979:                
                    980:                Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
                    981:                bind_grab = false;
                    982:                return menu_out_sound;
                    983:        }
1.1.1.2   root      984: 
1.1       root      985:        switch ( key )
                    986:        {
                    987:        case K_KP_ENTER:
                    988:        case K_ENTER:
                    989:                KeyBindingFunc( item );
                    990:                return menu_in_sound;
                    991:        case K_BACKSPACE:               // delete bindings
                    992:        case K_DEL:                             // delete bindings
                    993:        case K_KP_DEL:
                    994:                M_UnbindCommand( bindnames[item->generic.localdata[0]][0] );
                    995:                return menu_out_sound;
                    996:        default:
                    997:                return Default_MenuKey( &s_keys_menu, key );
                    998:        }
                    999: }
1.1.1.2   root     1000: 
1.1       root     1001: void M_Menu_Keys_f (void)
                   1002: {
                   1003:        Keys_MenuInit();
                   1004:        M_PushMenu( Keys_MenuDraw, Keys_MenuKey );
                   1005: }
1.1.1.2   root     1006: 
                   1007: 
1.1       root     1008: /*
                   1009: =======================================================================
1.1.1.2   root     1010: 
1.1       root     1011: CONTROLS MENU
1.1.1.2   root     1012: 
1.1       root     1013: =======================================================================
                   1014: */
                   1015: static cvar_t *win_noalttab;
                   1016: extern cvar_t *in_joystick;
1.1.1.2   root     1017: 
1.1       root     1018: static menuframework_s s_options_menu;
                   1019: static menuaction_s            s_options_defaults_action;
                   1020: static menuaction_s            s_options_customize_options_action;
                   1021: static menuslider_s            s_options_sensitivity_slider;
                   1022: static menulist_s              s_options_freelook_box;
                   1023: static menulist_s              s_options_noalttab_box;
                   1024: static menulist_s              s_options_alwaysrun_box;
                   1025: static menulist_s              s_options_invertmouse_box;
                   1026: static menulist_s              s_options_lookspring_box;
                   1027: static menulist_s              s_options_lookstrafe_box;
                   1028: static menulist_s              s_options_crosshair_box;
                   1029: static menuslider_s            s_options_sfxvolume_slider;
                   1030: static menulist_s              s_options_joystick_box;
                   1031: static menulist_s              s_options_cdvolume_box;
                   1032: static menulist_s              s_options_quality_list;
                   1033: static menulist_s              s_options_compatibility_list;
                   1034: static menulist_s              s_options_console_action;
                   1035: 
                   1036: static void CrosshairFunc( void *unused )
                   1037: {
                   1038:        Cvar_SetValue( "crosshair", s_options_crosshair_box.curvalue );
                   1039: }
                   1040: 
                   1041: static void JoystickFunc( void *unused )
                   1042: {
                   1043:        Cvar_SetValue( "in_joystick", s_options_joystick_box.curvalue );
                   1044: }
1.1.1.2   root     1045: 
1.1       root     1046: static void CustomizeControlsFunc( void *unused )
                   1047: {
                   1048:        M_Menu_Keys_f();
                   1049: }
1.1.1.2   root     1050: 
1.1       root     1051: static void AlwaysRunFunc( void *unused )
                   1052: {
                   1053:        Cvar_SetValue( "cl_run", s_options_alwaysrun_box.curvalue );
                   1054: }
1.1.1.2   root     1055: 
1.1       root     1056: static void FreeLookFunc( void *unused )
                   1057: {
                   1058:        Cvar_SetValue( "freelook", s_options_freelook_box.curvalue );
                   1059: }
1.1.1.2   root     1060: 
1.1       root     1061: static void MouseSpeedFunc( void *unused )
                   1062: {
                   1063:        Cvar_SetValue( "sensitivity", s_options_sensitivity_slider.curvalue / 2.0F );
                   1064: }
1.1.1.2   root     1065: 
1.1       root     1066: static void NoAltTabFunc( void *unused )
                   1067: {
                   1068:        Cvar_SetValue( "win_noalttab", s_options_noalttab_box.curvalue );
                   1069: }
1.1.1.2   root     1070: 
1.1       root     1071: static float ClampCvar( float min, float max, float value )
                   1072: {
                   1073:        if ( value < min ) return min;
                   1074:        if ( value > max ) return max;
                   1075:        return value;
                   1076: }
                   1077: 
                   1078: static void ControlsSetMenuItemValues( void )
                   1079: {
                   1080:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
                   1081:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
                   1082:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
                   1083:        s_options_sensitivity_slider.curvalue   = ( sensitivity->value ) * 2;
                   1084: 
                   1085:        Cvar_SetValue( "cl_run", ClampCvar( 0, 1, cl_run->value ) );
                   1086:        s_options_alwaysrun_box.curvalue                = cl_run->value;
                   1087: 
                   1088:        s_options_invertmouse_box.curvalue              = m_pitch->value < 0;
                   1089: 
                   1090:        Cvar_SetValue( "lookspring", ClampCvar( 0, 1, lookspring->value ) );
                   1091:        s_options_lookspring_box.curvalue               = lookspring->value;
                   1092: 
                   1093:        Cvar_SetValue( "lookstrafe", ClampCvar( 0, 1, lookstrafe->value ) );
                   1094:        s_options_lookstrafe_box.curvalue               = lookstrafe->value;
                   1095: 
                   1096:        Cvar_SetValue( "freelook", ClampCvar( 0, 1, freelook->value ) );
                   1097:        s_options_freelook_box.curvalue                 = freelook->value;
                   1098: 
                   1099:        Cvar_SetValue( "crosshair", ClampCvar( 0, 3, crosshair->value ) );
                   1100:        s_options_crosshair_box.curvalue                = crosshair->value;
                   1101: 
                   1102:        Cvar_SetValue( "in_joystick", ClampCvar( 0, 1, in_joystick->value ) );
                   1103:        s_options_joystick_box.curvalue         = in_joystick->value;
                   1104: 
                   1105:        s_options_noalttab_box.curvalue                 = win_noalttab->value;
                   1106: }
1.1.1.2   root     1107: 
1.1       root     1108: static void ControlsResetDefaultsFunc( void *unused )
                   1109: {
                   1110:        Cbuf_AddText ("exec default.cfg\n");
                   1111:        Cbuf_Execute();
                   1112: 
                   1113:        ControlsSetMenuItemValues();
                   1114: }
1.1.1.2   root     1115: 
1.1       root     1116: static void InvertMouseFunc( void *unused )
                   1117: {
                   1118:        Cvar_SetValue( "m_pitch", -m_pitch->value );
                   1119: }
1.1.1.2   root     1120: 
1.1       root     1121: static void LookspringFunc( void *unused )
                   1122: {
                   1123:        Cvar_SetValue( "lookspring", !lookspring->value );
                   1124: }
1.1.1.2   root     1125: 
1.1       root     1126: static void LookstrafeFunc( void *unused )
                   1127: {
                   1128:        Cvar_SetValue( "lookstrafe", !lookstrafe->value );
                   1129: }
1.1.1.2   root     1130: 
1.1       root     1131: static void UpdateVolumeFunc( void *unused )
                   1132: {
                   1133:        Cvar_SetValue( "s_volume", s_options_sfxvolume_slider.curvalue / 10 );
                   1134: }
                   1135: 
                   1136: static void UpdateCDVolumeFunc( void *unused )
                   1137: {
                   1138:        Cvar_SetValue( "cd_nocd", !s_options_cdvolume_box.curvalue );
                   1139: }
                   1140: 
                   1141: static void ConsoleFunc( void *unused )
                   1142: {
                   1143:        /*
                   1144:        ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
                   1145:        */
                   1146:        extern void Key_ClearTyping( void );
                   1147: 
                   1148:        if ( cl.attractloop )
                   1149:        {
                   1150:                Cbuf_AddText ("killserver\n");
                   1151:                return;
                   1152:        }
                   1153: 
                   1154:        Key_ClearTyping ();
                   1155:        Con_ClearNotify ();
                   1156: 
                   1157:        M_ForceMenuOff ();
                   1158:        cls.key_dest = key_console;
                   1159: }
                   1160: 
                   1161: static void UpdateSoundQualityFunc( void *unused )
                   1162: {
                   1163:        if ( s_options_quality_list.curvalue )
                   1164:        {
                   1165:                Cvar_SetValue( "s_khz", 22 );
                   1166:                Cvar_SetValue( "s_loadas8bit", false );
                   1167:        }
                   1168:        else
                   1169:        {
                   1170:                Cvar_SetValue( "s_khz", 11 );
                   1171:                Cvar_SetValue( "s_loadas8bit", true );
                   1172:        }
                   1173:        
                   1174:        Cvar_SetValue( "s_primary", s_options_compatibility_list.curvalue );
                   1175: 
                   1176:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
                   1177:        M_Print( 16 + 16, 120 - 48 + 8,  "Restarting the sound system. This" );
                   1178:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
                   1179:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
                   1180: 
                   1181:        // the text box won't show up unless we do a buffer swap
                   1182:        re.EndFrame();
                   1183: 
                   1184:        CL_Snd_Restart_f();
                   1185: }
                   1186: 
                   1187: void Options_MenuInit( void )
                   1188: {
                   1189:        static const char *cd_music_items[] =
                   1190:        {
                   1191:                "disabled",
                   1192:                "enabled",
                   1193:                0
                   1194:        };
                   1195:        static const char *quality_items[] =
                   1196:        {
                   1197:                "low", "high", 0
                   1198:        };
                   1199: 
                   1200:        static const char *compatibility_items[] =
                   1201:        {
                   1202:                "max compatibility", "max performance", 0
                   1203:        };
                   1204: 
                   1205:        static const char *yesno_names[] =
                   1206:        {
                   1207:                "no",
                   1208:                "yes",
                   1209:                0
                   1210:        };
1.1.1.2   root     1211: 
1.1       root     1212:        static const char *crosshair_names[] =
                   1213:        {
                   1214:                "none",
                   1215:                "cross",
                   1216:                "dot",
                   1217:                "angle",
                   1218:                0
                   1219:        };
1.1.1.2   root     1220: 
1.1       root     1221:        win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
1.1.1.2   root     1222: 
1.1       root     1223:        /*
                   1224:        ** configure controls menu and menu items
                   1225:        */
                   1226:        s_options_menu.x = viddef.width / 2;
                   1227:        s_options_menu.y = viddef.height / 2 - 58;
                   1228:        s_options_menu.nitems = 0;
                   1229: 
                   1230:        s_options_sfxvolume_slider.generic.type = MTYPE_SLIDER;
                   1231:        s_options_sfxvolume_slider.generic.x    = 0;
                   1232:        s_options_sfxvolume_slider.generic.y    = 0;
                   1233:        s_options_sfxvolume_slider.generic.name = "effects volume";
                   1234:        s_options_sfxvolume_slider.generic.callback     = UpdateVolumeFunc;
                   1235:        s_options_sfxvolume_slider.minvalue             = 0;
                   1236:        s_options_sfxvolume_slider.maxvalue             = 10;
                   1237:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
                   1238: 
                   1239:        s_options_cdvolume_box.generic.type     = MTYPE_SPINCONTROL;
                   1240:        s_options_cdvolume_box.generic.x                = 0;
                   1241:        s_options_cdvolume_box.generic.y                = 10;
                   1242:        s_options_cdvolume_box.generic.name     = "CD music";
                   1243:        s_options_cdvolume_box.generic.callback = UpdateCDVolumeFunc;
                   1244:        s_options_cdvolume_box.itemnames                = cd_music_items;
                   1245:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
                   1246: 
                   1247:        s_options_quality_list.generic.type     = MTYPE_SPINCONTROL;
                   1248:        s_options_quality_list.generic.x                = 0;
                   1249:        s_options_quality_list.generic.y                = 20;;
                   1250:        s_options_quality_list.generic.name             = "sound quality";
                   1251:        s_options_quality_list.generic.callback = UpdateSoundQualityFunc;
                   1252:        s_options_quality_list.itemnames                = quality_items;
                   1253:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
                   1254: 
                   1255:        s_options_compatibility_list.generic.type       = MTYPE_SPINCONTROL;
                   1256:        s_options_compatibility_list.generic.x          = 0;
                   1257:        s_options_compatibility_list.generic.y          = 30;
                   1258:        s_options_compatibility_list.generic.name       = "sound compatibility";
                   1259:        s_options_compatibility_list.generic.callback = UpdateSoundQualityFunc;
                   1260:        s_options_compatibility_list.itemnames          = compatibility_items;
                   1261:        s_options_compatibility_list.curvalue           = Cvar_VariableValue( "s_primary" );
                   1262: 
                   1263:        s_options_sensitivity_slider.generic.type       = MTYPE_SLIDER;
                   1264:        s_options_sensitivity_slider.generic.x          = 0;
                   1265:        s_options_sensitivity_slider.generic.y          = 50;
                   1266:        s_options_sensitivity_slider.generic.name       = "mouse speed";
                   1267:        s_options_sensitivity_slider.generic.callback = MouseSpeedFunc;
                   1268:        s_options_sensitivity_slider.minvalue           = 2;
                   1269:        s_options_sensitivity_slider.maxvalue           = 22;
1.1.1.2   root     1270: 
1.1       root     1271:        s_options_alwaysrun_box.generic.type = MTYPE_SPINCONTROL;
                   1272:        s_options_alwaysrun_box.generic.x       = 0;
                   1273:        s_options_alwaysrun_box.generic.y       = 60;
                   1274:        s_options_alwaysrun_box.generic.name    = "always run";
                   1275:        s_options_alwaysrun_box.generic.callback = AlwaysRunFunc;
                   1276:        s_options_alwaysrun_box.itemnames = yesno_names;
1.1.1.2   root     1277: 
1.1       root     1278:        s_options_invertmouse_box.generic.type = MTYPE_SPINCONTROL;
                   1279:        s_options_invertmouse_box.generic.x     = 0;
                   1280:        s_options_invertmouse_box.generic.y     = 70;
                   1281:        s_options_invertmouse_box.generic.name  = "invert mouse";
                   1282:        s_options_invertmouse_box.generic.callback = InvertMouseFunc;
                   1283:        s_options_invertmouse_box.itemnames = yesno_names;
1.1.1.2   root     1284: 
1.1       root     1285:        s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
                   1286:        s_options_lookspring_box.generic.x      = 0;
                   1287:        s_options_lookspring_box.generic.y      = 80;
                   1288:        s_options_lookspring_box.generic.name   = "lookspring";
                   1289:        s_options_lookspring_box.generic.callback = LookspringFunc;
                   1290:        s_options_lookspring_box.itemnames = yesno_names;
1.1.1.2   root     1291: 
1.1       root     1292:        s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
                   1293:        s_options_lookstrafe_box.generic.x      = 0;
                   1294:        s_options_lookstrafe_box.generic.y      = 90;
                   1295:        s_options_lookstrafe_box.generic.name   = "lookstrafe";
                   1296:        s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
                   1297:        s_options_lookstrafe_box.itemnames = yesno_names;
1.1.1.2   root     1298: 
1.1       root     1299:        s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
                   1300:        s_options_freelook_box.generic.x        = 0;
                   1301:        s_options_freelook_box.generic.y        = 100;
                   1302:        s_options_freelook_box.generic.name     = "free look";
                   1303:        s_options_freelook_box.generic.callback = FreeLookFunc;
                   1304:        s_options_freelook_box.itemnames = yesno_names;
                   1305: 
                   1306:        s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
                   1307:        s_options_crosshair_box.generic.x       = 0;
                   1308:        s_options_crosshair_box.generic.y       = 110;
                   1309:        s_options_crosshair_box.generic.name    = "crosshair";
                   1310:        s_options_crosshair_box.generic.callback = CrosshairFunc;
                   1311:        s_options_crosshair_box.itemnames = crosshair_names;
                   1312: /*
                   1313:        s_options_noalttab_box.generic.type = MTYPE_SPINCONTROL;
                   1314:        s_options_noalttab_box.generic.x        = 0;
                   1315:        s_options_noalttab_box.generic.y        = 110;
                   1316:        s_options_noalttab_box.generic.name     = "disable alt-tab";
                   1317:        s_options_noalttab_box.generic.callback = NoAltTabFunc;
                   1318:        s_options_noalttab_box.itemnames = yesno_names;
                   1319: */
                   1320:        s_options_joystick_box.generic.type = MTYPE_SPINCONTROL;
                   1321:        s_options_joystick_box.generic.x        = 0;
                   1322:        s_options_joystick_box.generic.y        = 120;
                   1323:        s_options_joystick_box.generic.name     = "use joystick";
                   1324:        s_options_joystick_box.generic.callback = JoystickFunc;
                   1325:        s_options_joystick_box.itemnames = yesno_names;
                   1326: 
                   1327:        s_options_customize_options_action.generic.type = MTYPE_ACTION;
                   1328:        s_options_customize_options_action.generic.x            = 0;
                   1329:        s_options_customize_options_action.generic.y            = 140;
                   1330:        s_options_customize_options_action.generic.name = "customize controls";
                   1331:        s_options_customize_options_action.generic.callback = CustomizeControlsFunc;
1.1.1.2   root     1332: 
1.1       root     1333:        s_options_defaults_action.generic.type  = MTYPE_ACTION;
                   1334:        s_options_defaults_action.generic.x             = 0;
                   1335:        s_options_defaults_action.generic.y             = 150;
                   1336:        s_options_defaults_action.generic.name  = "reset defaults";
                   1337:        s_options_defaults_action.generic.callback = ControlsResetDefaultsFunc;
                   1338: 
                   1339:        s_options_console_action.generic.type   = MTYPE_ACTION;
                   1340:        s_options_console_action.generic.x              = 0;
                   1341:        s_options_console_action.generic.y              = 160;
                   1342:        s_options_console_action.generic.name   = "go to console";
                   1343:        s_options_console_action.generic.callback = ConsoleFunc;
                   1344: 
                   1345:        ControlsSetMenuItemValues();
                   1346: 
                   1347:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sfxvolume_slider );
                   1348:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_cdvolume_box );
                   1349:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_quality_list );
                   1350:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_compatibility_list );
                   1351:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sensitivity_slider );
                   1352:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_alwaysrun_box );
                   1353:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_invertmouse_box );
                   1354:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookspring_box );
                   1355:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookstrafe_box );
                   1356:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_freelook_box );
                   1357:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_crosshair_box );
                   1358:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_joystick_box );
                   1359:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_customize_options_action );
                   1360:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_defaults_action );
                   1361:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_console_action );
                   1362: }
1.1.1.2   root     1363: 
1.1       root     1364: void Options_MenuDraw (void)
                   1365: {
                   1366:        M_Banner( "m_banner_options" );
                   1367:        Menu_AdjustCursor( &s_options_menu, 1 );
                   1368:        Menu_Draw( &s_options_menu );
                   1369: }
1.1.1.2   root     1370: 
1.1       root     1371: const char *Options_MenuKey( int key )
                   1372: {
                   1373:        return Default_MenuKey( &s_options_menu, key );
                   1374: }
1.1.1.2   root     1375: 
1.1       root     1376: void M_Menu_Options_f (void)
                   1377: {
                   1378:        Options_MenuInit();
                   1379:        M_PushMenu ( Options_MenuDraw, Options_MenuKey );
                   1380: }
1.1.1.2   root     1381: 
1.1       root     1382: /*
                   1383: =======================================================================
1.1.1.2   root     1384: 
1.1       root     1385: VIDEO MENU
1.1.1.2   root     1386: 
1.1       root     1387: =======================================================================
                   1388: */
1.1.1.2   root     1389: 
1.1       root     1390: void M_Menu_Video_f (void)
                   1391: {
                   1392:        VID_MenuInit();
                   1393:        M_PushMenu( VID_MenuDraw, VID_MenuKey );
                   1394: }
1.1.1.2   root     1395: 
1.1       root     1396: /*
                   1397: =============================================================================
                   1398: 
                   1399: END GAME MENU
                   1400: 
                   1401: =============================================================================
                   1402: */
                   1403: static int credits_start_time;
1.1.1.2   root     1404: static const char **credits;
                   1405: static char *creditsIndex[256];
                   1406: static char *creditsBuffer;
                   1407: static const char *idcredits[] =
1.1       root     1408: {
                   1409:        "+QUAKE II BY ID SOFTWARE",
                   1410:        "",
                   1411:        "+PROGRAMMING",
                   1412:        "John Carmack",
                   1413:        "John Cash",
                   1414:        "Brian Hook",
                   1415:        "",
                   1416:        "+ART",
                   1417:        "Adrian Carmack",
                   1418:        "Kevin Cloud",
                   1419:        "Paul Steed",
                   1420:        "",
                   1421:        "+LEVEL DESIGN",
                   1422:        "Tim Willits",
                   1423:        "American McGee",
                   1424:        "Christian Antkow",
                   1425:        "Paul Jaquays",
                   1426:        "Brandon James",
                   1427:        "",
                   1428:        "+BIZ",
                   1429:        "Todd Hollenshead",
                   1430:        "Barrett (Bear) Alexander",
                   1431:        "Donna Jackson",
                   1432:        "",
                   1433:        "",
                   1434:        "+SPECIAL THANKS",
                   1435:        "Ben Donges for beta testing",
                   1436:        "",
                   1437:        "",
                   1438:        "",
                   1439:        "",
                   1440:        "",
                   1441:        "",
                   1442:        "+ADDITIONAL SUPPORT",
                   1443:        "",
                   1444:        "+LINUX PORT AND CTF",
                   1445:        "Dave \"Zoid\" Kirsch",
                   1446:        "",
                   1447:        "+CINEMATIC SEQUENCES",
                   1448:        "Ending Cinematic by Blur Studio - ",
                   1449:        "Venice, CA",
                   1450:        "",
                   1451:        "Environment models for Introduction",
                   1452:        "Cinematic by Karl Dolgener",
                   1453:        "",
                   1454:        "Assistance with environment design",
                   1455:        "by Cliff Iwai",
                   1456:        "",
                   1457:        "+SOUND EFFECTS AND MUSIC",
                   1458:        "Sound Design by Soundelux Media Labs.",
                   1459:        "Music Composed and Produced by",
                   1460:        "Soundelux Media Labs.  Special thanks",
                   1461:        "to Bill Brown, Tom Ozanich, Brian",
                   1462:        "Celano, Jeff Eisner, and The Soundelux",
                   1463:        "Players.",
                   1464:        "",
                   1465:        "\"Level Music\" by Sonic Mayhem",
                   1466:        "www.sonicmayhem.com",
                   1467:        "",
                   1468:        "\"Quake II Theme Song\"",
                   1469:        "(C) 1997 Rob Zombie. All Rights",
                   1470:        "Reserved.",
                   1471:        "",
                   1472:        "Track 10 (\"Climb\") by Jer Sypult",
                   1473:        "",
                   1474:        "Voice of computers by",
                   1475:        "Carly Staehlin-Taylor",
                   1476:        "",
                   1477:        "+THANKS TO ACTIVISION",
                   1478:        "+IN PARTICULAR:",
                   1479:        "",
                   1480:        "John Tam",
                   1481:        "Steve Rosenthal",
                   1482:        "Marty Stratton",
                   1483:        "Henk Hartong",
                   1484:        "",
                   1485:        "Quake II(tm) (C)1997 Id Software, Inc.",
                   1486:        "All Rights Reserved.  Distributed by",
                   1487:        "Activision, Inc. under license.",
                   1488:        "Quake II(tm), the Id Software name,",
                   1489:        "the \"Q II\"(tm) logo and id(tm)",
                   1490:        "logo are trademarks of Id Software,",
                   1491:        "Inc. Activision(R) is a registered",
                   1492:        "trademark of Activision, Inc. All",
                   1493:        "other trademarks and trade names are",
                   1494:        "properties of their respective owners.",
                   1495:        0
                   1496: };
                   1497: 
1.1.1.2   root     1498: static const char *xatcredits[] =
                   1499: {
                   1500:        "+QUAKE II MISSION PACK: THE RECKONING",
                   1501:        "+BY",
                   1502:        "+XATRIX ENTERTAINMENT, INC.",
                   1503:        "",
                   1504:        "+DESIGN AND DIRECTION",
                   1505:        "Drew Markham",
                   1506:        "",
                   1507:        "+PRODUCED BY",
                   1508:        "Greg Goodrich",
                   1509:        "",
                   1510:        "+PROGRAMMING",
                   1511:        "Rafael Paiz",
                   1512:        "",
                   1513:        "+LEVEL DESIGN / ADDITIONAL GAME DESIGN",
                   1514:        "Alex Mayberry",
                   1515:        "",
                   1516:        "+LEVEL DESIGN",
                   1517:        "Mal Blackwell",
                   1518:        "Dan Koppel",
                   1519:        "",
                   1520:        "+ART DIRECTION",
                   1521:        "Michael \"Maxx\" Kaufman",
                   1522:        "",
                   1523:        "+COMPUTER GRAPHICS SUPERVISOR AND",
                   1524:        "+CHARACTER ANIMATION DIRECTION",
                   1525:        "Barry Dempsey",
                   1526:        "",
                   1527:        "+SENIOR ANIMATOR AND MODELER",
                   1528:        "Jason Hoover",
                   1529:        "",
                   1530:        "+CHARACTER ANIMATION AND",
                   1531:        "+MOTION CAPTURE SPECIALIST",
                   1532:        "Amit Doron",
                   1533:        "",
                   1534:        "+ART",
                   1535:        "Claire Praderie-Markham",
                   1536:        "Viktor Antonov",
                   1537:        "Corky Lehmkuhl",
                   1538:        "",
                   1539:        "+INTRODUCTION ANIMATION",
                   1540:        "Dominique Drozdz",
                   1541:        "",
                   1542:        "+ADDITIONAL LEVEL DESIGN",
                   1543:        "Aaron Barber",
                   1544:        "Rhett Baldwin",
                   1545:        "",
                   1546:        "+3D CHARACTER ANIMATION TOOLS",
                   1547:        "Gerry Tyra, SA Technology",
                   1548:        "",
                   1549:        "+ADDITIONAL EDITOR TOOL PROGRAMMING",
                   1550:        "Robert Duffy",
                   1551:        "",
                   1552:        "+ADDITIONAL PROGRAMMING",
                   1553:        "Ryan Feltrin",
                   1554:        "",
                   1555:        "+PRODUCTION COORDINATOR",
                   1556:        "Victoria Sylvester",
                   1557:        "",
                   1558:        "+SOUND DESIGN",
                   1559:        "Gary Bradfield",
                   1560:        "",
                   1561:        "+MUSIC BY",
                   1562:        "Sonic Mayhem",
                   1563:        "",
                   1564:        "",
                   1565:        "",
                   1566:        "+SPECIAL THANKS",
                   1567:        "+TO",
                   1568:        "+OUR FRIENDS AT ID SOFTWARE",
                   1569:        "",
                   1570:        "John Carmack",
                   1571:        "John Cash",
                   1572:        "Brian Hook",
                   1573:        "Adrian Carmack",
                   1574:        "Kevin Cloud",
                   1575:        "Paul Steed",
                   1576:        "Tim Willits",
                   1577:        "Christian Antkow",
                   1578:        "Paul Jaquays",
                   1579:        "Brandon James",
                   1580:        "Todd Hollenshead",
                   1581:        "Barrett (Bear) Alexander",
                   1582:        "Dave \"Zoid\" Kirsch",
                   1583:        "Donna Jackson",
                   1584:        "",
                   1585:        "",
                   1586:        "",
                   1587:        "+THANKS TO ACTIVISION",
                   1588:        "+IN PARTICULAR:",
                   1589:        "",
                   1590:        "Marty Stratton",
                   1591:        "Henk \"The Original Ripper\" Hartong",
                   1592:        "Kevin Kraff",
                   1593:        "Jamey Gottlieb",
                   1594:        "Chris Hepburn",
                   1595:        "",
                   1596:        "+AND THE GAME TESTERS",
                   1597:        "",
                   1598:        "Tim Vanlaw",
                   1599:        "Doug Jacobs",
                   1600:        "Steven Rosenthal",
                   1601:        "David Baker",
                   1602:        "Chris Campbell",
                   1603:        "Aaron Casillas",
                   1604:        "Steve Elwell",
                   1605:        "Derek Johnstone",
                   1606:        "Igor Krinitskiy",
                   1607:        "Samantha Lee",
                   1608:        "Michael Spann",
                   1609:        "Chris Toft",
                   1610:        "Juan Valdes",
                   1611:        "",
                   1612:        "+THANKS TO INTERGRAPH COMPUTER SYTEMS",
                   1613:        "+IN PARTICULAR:",
                   1614:        "",
                   1615:        "Michael T. Nicolaou",
                   1616:        "",
                   1617:        "",
                   1618:        "Quake II Mission Pack: The Reckoning",
                   1619:        "(tm) (C)1998 Id Software, Inc. All",
                   1620:        "Rights Reserved. Developed by Xatrix",
                   1621:        "Entertainment, Inc. for Id Software,",
                   1622:        "Inc. Distributed by Activision Inc.",
                   1623:        "under license. Quake(R) is a",
                   1624:        "registered trademark of Id Software,",
                   1625:        "Inc. Quake II Mission Pack: The",
                   1626:        "Reckoning(tm), Quake II(tm), the Id",
                   1627:        "Software name, the \"Q II\"(tm) logo",
                   1628:        "and id(tm) logo are trademarks of Id",
                   1629:        "Software, Inc. Activision(R) is a",
                   1630:        "registered trademark of Activision,",
                   1631:        "Inc. Xatrix(R) is a registered",
                   1632:        "trademark of Xatrix Entertainment,",
                   1633:        "Inc. All other trademarks and trade",
                   1634:        "names are properties of their",
                   1635:        "respective owners.",
                   1636:        0
                   1637: };
                   1638: 
1.1.1.3   root     1639: static const char *roguecredits[] =
                   1640: {
                   1641:        "+QUAKE II MISSION PACK 2: GROUND ZERO",
                   1642:        "+BY",
                   1643:        "+ROGUE ENTERTAINMENT, INC.",
                   1644:        "",
                   1645:        "+PRODUCED BY",
                   1646:        "Jim Molinets",
                   1647:        "",
                   1648:        "+PROGRAMMING",
                   1649:        "Peter Mack",
                   1650:        "Patrick Magruder",
                   1651:        "",
                   1652:        "+LEVEL DESIGN",
                   1653:        "Jim Molinets",
                   1654:        "Cameron Lamprecht",
                   1655:        "Berenger Fish",
                   1656:        "Robert Selitto",
                   1657:        "Steve Tietze",
                   1658:        "Steve Thoms",
                   1659:        "",
                   1660:        "+ART DIRECTION",
                   1661:        "Rich Fleider",
                   1662:        "",
                   1663:        "+ART",
                   1664:        "Rich Fleider",
                   1665:        "Steve Maines",
                   1666:        "Won Choi",
                   1667:        "",
                   1668:        "+ANIMATION SEQUENCES",
                   1669:        "Creat Studios",
                   1670:        "Steve Maines",
                   1671:        "",
                   1672:        "+ADDITIONAL LEVEL DESIGN",
                   1673:        "Rich Fleider",
                   1674:        "Steve Maines",
                   1675:        "Peter Mack",
                   1676:        "",
                   1677:        "+SOUND",
                   1678:        "James Grunke",
                   1679:        "",
                   1680:        "+GROUND ZERO THEME",
                   1681:        "+AND",
                   1682:        "+MUSIC BY",
                   1683:        "Sonic Mayhem",
                   1684:        "",
                   1685:        "+VWEP MODELS",
                   1686:        "Brent \"Hentai\" Dill",
                   1687:        "",
                   1688:        "",
                   1689:        "",
                   1690:        "+SPECIAL THANKS",
                   1691:        "+TO",
                   1692:        "+OUR FRIENDS AT ID SOFTWARE",
                   1693:        "",
                   1694:        "John Carmack",
                   1695:        "John Cash",
                   1696:        "Brian Hook",
                   1697:        "Adrian Carmack",
                   1698:        "Kevin Cloud",
                   1699:        "Paul Steed",
                   1700:        "Tim Willits",
                   1701:        "Christian Antkow",
                   1702:        "Paul Jaquays",
                   1703:        "Brandon James",
                   1704:        "Todd Hollenshead",
                   1705:        "Barrett (Bear) Alexander",
                   1706:        "Katherine Anna Kang",
                   1707:        "Donna Jackson",
                   1708:        "Dave \"Zoid\" Kirsch",
                   1709:        "",
                   1710:        "",
                   1711:        "",
                   1712:        "+THANKS TO ACTIVISION",
                   1713:        "+IN PARTICULAR:",
                   1714:        "",
                   1715:        "Marty Stratton",
                   1716:        "Henk Hartong",
                   1717:        "Mitch Lasky",
                   1718:        "Steve Rosenthal",
                   1719:        "Steve Elwell",
                   1720:        "",
                   1721:        "+AND THE GAME TESTERS",
                   1722:        "",
                   1723:        "The Ranger Clan",
                   1724:        "Dave \"Zoid\" Kirsch",
                   1725:        "Nihilistic Software",
                   1726:        "Robert Duffy",
                   1727:        "",
                   1728:        "And Countless Others",
                   1729:        "",
                   1730:        "",
                   1731:        "",
                   1732:        "Quake II Mission Pack 2: Ground Zero",
                   1733:        "(tm) (C)1998 Id Software, Inc. All",
                   1734:        "Rights Reserved. Developed by Rogue",
                   1735:        "Entertainment, Inc. for Id Software,",
                   1736:        "Inc. Distributed by Activision Inc.",
                   1737:        "under license. Quake(R) is a",
                   1738:        "registered trademark of Id Software,",
                   1739:        "Inc. Quake II Mission Pack 2: Ground",
                   1740:        "Zero(tm), Quake II(tm), the Id",
                   1741:        "Software name, the \"Q II\"(tm) logo",
                   1742:        "and id(tm) logo are trademarks of Id",
                   1743:        "Software, Inc. Activision(R) is a",
                   1744:        "registered trademark of Activision,",
                   1745:        "Inc. Rogue(R) is a registered",
                   1746:        "trademark of Rogue Entertainment,",
                   1747:        "Inc. All other trademarks and trade",
                   1748:        "names are properties of their",
                   1749:        "respective owners.",
                   1750:        0
                   1751: };
                   1752: 
                   1753: 
1.1       root     1754: void M_Credits_MenuDraw( void )
                   1755: {
                   1756:        int i, y;
                   1757: 
                   1758:        /*
                   1759:        ** draw the credits
                   1760:        */
                   1761:        for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ )
                   1762:        {
                   1763:                int j, stringoffset = 0;
                   1764:                int bold = false;
                   1765: 
                   1766:                if ( y <= -8 )
                   1767:                        continue;
                   1768: 
                   1769:                if ( credits[i][0] == '+' )
                   1770:                {
                   1771:                        bold = true;
                   1772:                        stringoffset = 1;
                   1773:                }
                   1774:                else
                   1775:                {
                   1776:                        bold = false;
                   1777:                        stringoffset = 0;
                   1778:                }
                   1779: 
                   1780:                for ( j = 0; credits[i][j+stringoffset]; j++ )
                   1781:                {
                   1782:                        int x;
                   1783: 
                   1784:                        x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8;
                   1785: 
                   1786:                        if ( bold )
                   1787:                                re.DrawChar( x, y, credits[i][j+stringoffset] + 128 );
                   1788:                        else
                   1789:                                re.DrawChar( x, y, credits[i][j+stringoffset] );
                   1790:                }
                   1791:        }
                   1792: 
                   1793:        if ( y < 0 )
                   1794:                credits_start_time = cls.realtime;
                   1795: }
                   1796: 
                   1797: const char *M_Credits_Key( int key )
                   1798: {
                   1799:        switch (key)
                   1800:        {
                   1801:        case K_ESCAPE:
1.1.1.2   root     1802:                if (creditsBuffer)
                   1803:                        FS_FreeFile (creditsBuffer);
1.1       root     1804:                M_PopMenu ();
                   1805:                break;
                   1806:        }
                   1807: 
                   1808:        return menu_out_sound;
                   1809: 
                   1810: }
                   1811: 
1.1.1.2   root     1812: extern int Developer_searchpath (int who);
                   1813: 
1.1       root     1814: void M_Menu_Credits_f( void )
                   1815: {
1.1.1.2   root     1816:        int             n;
                   1817:        int             count;
                   1818:        char    *p;
                   1819:        int             isdeveloper = 0;
                   1820: 
                   1821:        creditsBuffer = NULL;
                   1822:        count = FS_LoadFile ("credits", &creditsBuffer);
                   1823:        if (count != -1)
                   1824:        {
                   1825:                p = creditsBuffer;
                   1826:                for (n = 0; n < 255; n++)
                   1827:                {
                   1828:                        creditsIndex[n] = p;
                   1829:                        while (*p != '\r' && *p != '\n')
                   1830:                        {
                   1831:                                p++;
                   1832:                                if (--count == 0)
                   1833:                                        break;
                   1834:                        }
                   1835:                        if (*p == '\r')
                   1836:                        {
                   1837:                                *p++ = 0;
                   1838:                                if (--count == 0)
                   1839:                                        break;
                   1840:                        }
                   1841:                        *p++ = 0;
                   1842:                        if (--count == 0)
                   1843:                                break;
                   1844:                }
                   1845:                creditsIndex[++n] = 0;
                   1846:                credits = creditsIndex;
                   1847:        }
                   1848:        else
                   1849:        {
                   1850:                isdeveloper = Developer_searchpath (1);
                   1851:                
1.1.1.3   root     1852:                if (isdeveloper == 1)                   // xatrix
1.1.1.2   root     1853:                        credits = xatcredits;
1.1.1.3   root     1854:                else if (isdeveloper == 2)              // ROGUE
                   1855:                        credits = roguecredits;
1.1.1.2   root     1856:                else
                   1857:                {
                   1858:                        credits = idcredits;    
                   1859:                }
                   1860: 
                   1861:        }
                   1862: 
1.1       root     1863:        credits_start_time = cls.realtime;
                   1864:        M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
                   1865: }
1.1.1.2   root     1866: 
1.1       root     1867: /*
                   1868: =============================================================================
                   1869: 
                   1870: GAME MENU
                   1871: 
                   1872: =============================================================================
                   1873: */
1.1.1.2   root     1874: 
1.1       root     1875: static int             m_game_cursor;
1.1.1.2   root     1876: 
1.1       root     1877: static menuframework_s s_game_menu;
                   1878: static menuaction_s            s_easy_game_action;
                   1879: static menuaction_s            s_medium_game_action;
                   1880: static menuaction_s            s_hard_game_action;
                   1881: static menuaction_s            s_load_game_action;
                   1882: static menuaction_s            s_save_game_action;
                   1883: static menuaction_s            s_credits_action;
                   1884: static menuseparator_s s_blankline;
1.1.1.2   root     1885: 
1.1       root     1886: static void StartGame( void )
                   1887: {
                   1888:        // disable updates and start the cinematic going
                   1889:        cl.servercount = -1;
                   1890:        M_ForceMenuOff ();
                   1891:        Cvar_SetValue( "deathmatch", 0 );
                   1892:        Cvar_SetValue( "coop", 0 );
1.1.1.3   root     1893: 
                   1894:        Cvar_SetValue( "gamerules", 0 );                //PGM
                   1895: 
1.1       root     1896:        Cbuf_AddText ("loading ; killserver ; wait ; newgame\n");
                   1897:        cls.key_dest = key_game;
                   1898: }
1.1.1.2   root     1899: 
1.1       root     1900: static void EasyGameFunc( void *data )
                   1901: {
                   1902:        Cvar_ForceSet( "skill", "0" );
                   1903:        StartGame();
                   1904: }
1.1.1.2   root     1905: 
1.1       root     1906: static void MediumGameFunc( void *data )
                   1907: {
                   1908:        Cvar_ForceSet( "skill", "1" );
                   1909:        StartGame();
                   1910: }
1.1.1.2   root     1911: 
1.1       root     1912: static void HardGameFunc( void *data )
                   1913: {
                   1914:        Cvar_ForceSet( "skill", "2" );
                   1915:        StartGame();
                   1916: }
1.1.1.2   root     1917: 
1.1       root     1918: static void LoadGameFunc( void *unused )
                   1919: {
                   1920:        M_Menu_LoadGame_f ();
                   1921: }
1.1.1.2   root     1922: 
1.1       root     1923: static void SaveGameFunc( void *unused )
                   1924: {
                   1925:        M_Menu_SaveGame_f();
                   1926: }
1.1.1.2   root     1927: 
1.1       root     1928: static void CreditsFunc( void *unused )
                   1929: {
                   1930:        M_Menu_Credits_f();
                   1931: }
1.1.1.2   root     1932: 
1.1       root     1933: void Game_MenuInit( void )
                   1934: {
                   1935:        static const char *difficulty_names[] =
                   1936:        {
                   1937:                "easy",
                   1938:                "medium",
                   1939:                "hard",
                   1940:                0
                   1941:        };
1.1.1.2   root     1942: 
1.1       root     1943:        s_game_menu.x = viddef.width * 0.50;
                   1944:        s_game_menu.nitems = 0;
1.1.1.2   root     1945: 
1.1       root     1946:        s_easy_game_action.generic.type = MTYPE_ACTION;
                   1947:        s_easy_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1948:        s_easy_game_action.generic.x            = 0;
                   1949:        s_easy_game_action.generic.y            = 0;
                   1950:        s_easy_game_action.generic.name = "easy";
                   1951:        s_easy_game_action.generic.callback = EasyGameFunc;
1.1.1.2   root     1952: 
1.1       root     1953:        s_medium_game_action.generic.type       = MTYPE_ACTION;
                   1954:        s_medium_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1955:        s_medium_game_action.generic.x          = 0;
                   1956:        s_medium_game_action.generic.y          = 10;
                   1957:        s_medium_game_action.generic.name       = "medium";
                   1958:        s_medium_game_action.generic.callback = MediumGameFunc;
1.1.1.2   root     1959: 
1.1       root     1960:        s_hard_game_action.generic.type = MTYPE_ACTION;
                   1961:        s_hard_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1962:        s_hard_game_action.generic.x            = 0;
                   1963:        s_hard_game_action.generic.y            = 20;
                   1964:        s_hard_game_action.generic.name = "hard";
                   1965:        s_hard_game_action.generic.callback = HardGameFunc;
1.1.1.2   root     1966: 
1.1       root     1967:        s_blankline.generic.type = MTYPE_SEPARATOR;
                   1968: 
                   1969:        s_load_game_action.generic.type = MTYPE_ACTION;
                   1970:        s_load_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1971:        s_load_game_action.generic.x            = 0;
                   1972:        s_load_game_action.generic.y            = 40;
                   1973:        s_load_game_action.generic.name = "load game";
                   1974:        s_load_game_action.generic.callback = LoadGameFunc;
1.1.1.2   root     1975: 
1.1       root     1976:        s_save_game_action.generic.type = MTYPE_ACTION;
                   1977:        s_save_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1978:        s_save_game_action.generic.x            = 0;
                   1979:        s_save_game_action.generic.y            = 50;
                   1980:        s_save_game_action.generic.name = "save game";
                   1981:        s_save_game_action.generic.callback = SaveGameFunc;
                   1982: 
                   1983:        s_credits_action.generic.type   = MTYPE_ACTION;
                   1984:        s_credits_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   1985:        s_credits_action.generic.x              = 0;
                   1986:        s_credits_action.generic.y              = 60;
                   1987:        s_credits_action.generic.name   = "credits";
                   1988:        s_credits_action.generic.callback = CreditsFunc;
1.1.1.2   root     1989: 
1.1       root     1990:        Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action );
                   1991:        Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action );
                   1992:        Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action );
                   1993:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
                   1994:        Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action );
                   1995:        Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action );
                   1996:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
                   1997:        Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action );
1.1.1.2   root     1998: 
1.1       root     1999:        Menu_Center( &s_game_menu );
                   2000: }
1.1.1.2   root     2001: 
1.1       root     2002: void Game_MenuDraw( void )
                   2003: {
                   2004:        M_Banner( "m_banner_game" );
                   2005:        Menu_AdjustCursor( &s_game_menu, 1 );
                   2006:        Menu_Draw( &s_game_menu );
                   2007: }
1.1.1.2   root     2008: 
1.1       root     2009: const char *Game_MenuKey( int key )
                   2010: {
                   2011:        return Default_MenuKey( &s_game_menu, key );
                   2012: }
1.1.1.2   root     2013: 
1.1       root     2014: void M_Menu_Game_f (void)
                   2015: {
                   2016:        Game_MenuInit();
                   2017:        M_PushMenu( Game_MenuDraw, Game_MenuKey );
                   2018:        m_game_cursor = 1;
                   2019: }
1.1.1.2   root     2020: 
1.1       root     2021: /*
                   2022: =============================================================================
1.1.1.2   root     2023: 
1.1       root     2024: LOADGAME MENU
1.1.1.2   root     2025: 
1.1       root     2026: =============================================================================
                   2027: */
1.1.1.2   root     2028: 
1.1       root     2029: #define        MAX_SAVEGAMES   15
1.1.1.2   root     2030: 
1.1       root     2031: static menuframework_s s_savegame_menu;
1.1.1.2   root     2032: 
1.1       root     2033: static menuframework_s s_loadgame_menu;
                   2034: static menuaction_s            s_loadgame_actions[MAX_SAVEGAMES];
1.1.1.2   root     2035: 
1.1       root     2036: char           m_savestrings[MAX_SAVEGAMES][32];
                   2037: qboolean       m_savevalid[MAX_SAVEGAMES];
1.1.1.2   root     2038: 
1.1       root     2039: void Create_Savestrings (void)
                   2040: {
                   2041:        int             i;
                   2042:        FILE    *f;
                   2043:        char    name[MAX_OSPATH];
1.1.1.2   root     2044: 
1.1       root     2045:        for (i=0 ; i<MAX_SAVEGAMES ; i++)
                   2046:        {
                   2047:                Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i);
                   2048:                f = fopen (name, "rb");
                   2049:                if (!f)
                   2050:                {
                   2051:                        strcpy (m_savestrings[i], "<EMPTY>");
                   2052:                        m_savevalid[i] = false;
                   2053:                }
                   2054:                else
                   2055:                {
                   2056:                        FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f);
                   2057:                        fclose (f);
                   2058:                        m_savevalid[i] = true;
                   2059:                }
                   2060:        }
                   2061: }
1.1.1.2   root     2062: 
1.1       root     2063: void LoadGameCallback( void *self )
                   2064: {
                   2065:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root     2066: 
1.1       root     2067:        if ( m_savevalid[ a->generic.localdata[0] ] )
                   2068:                Cbuf_AddText (va("load save%i\n",  a->generic.localdata[0] ) );
                   2069:        M_ForceMenuOff ();
                   2070: }
1.1.1.2   root     2071: 
1.1       root     2072: void LoadGame_MenuInit( void )
                   2073: {
                   2074:        int i;
1.1.1.2   root     2075: 
1.1       root     2076:        s_loadgame_menu.x = viddef.width / 2 - 120;
                   2077:        s_loadgame_menu.y = viddef.height / 2 - 58;
                   2078:        s_loadgame_menu.nitems = 0;
1.1.1.2   root     2079: 
1.1       root     2080:        Create_Savestrings();
1.1.1.2   root     2081: 
1.1       root     2082:        for ( i = 0; i < MAX_SAVEGAMES; i++ )
                   2083:        {
                   2084:                s_loadgame_actions[i].generic.name                      = m_savestrings[i];
                   2085:                s_loadgame_actions[i].generic.flags                     = QMF_LEFT_JUSTIFY;
                   2086:                s_loadgame_actions[i].generic.localdata[0]      = i;
                   2087:                s_loadgame_actions[i].generic.callback          = LoadGameCallback;
1.1.1.2   root     2088: 
1.1       root     2089:                s_loadgame_actions[i].generic.x = 0;
                   2090:                s_loadgame_actions[i].generic.y = ( i ) * 10;
                   2091:                if (i>0)        // separate from autosave
                   2092:                        s_loadgame_actions[i].generic.y += 10;
1.1.1.2   root     2093: 
1.1       root     2094:                s_loadgame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2   root     2095: 
1.1       root     2096:                Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] );
                   2097:        }
                   2098: }
1.1.1.2   root     2099: 
1.1       root     2100: void LoadGame_MenuDraw( void )
                   2101: {
                   2102:        M_Banner( "m_banner_load_game" );
                   2103: //     Menu_AdjustCursor( &s_loadgame_menu, 1 );
                   2104:        Menu_Draw( &s_loadgame_menu );
                   2105: }
1.1.1.2   root     2106: 
1.1       root     2107: const char *LoadGame_MenuKey( int key )
                   2108: {
                   2109:        if ( key == K_ESCAPE || key == K_ENTER )
                   2110:        {
                   2111:                s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
                   2112:                if ( s_savegame_menu.cursor < 0 )
                   2113:                        s_savegame_menu.cursor = 0;
                   2114:        }
                   2115:        return Default_MenuKey( &s_loadgame_menu, key );
                   2116: }
1.1.1.2   root     2117: 
1.1       root     2118: void M_Menu_LoadGame_f (void)
                   2119: {
                   2120:        LoadGame_MenuInit();
                   2121:        M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey );
                   2122: }
1.1.1.2   root     2123: 
                   2124: 
1.1       root     2125: /*
                   2126: =============================================================================
1.1.1.2   root     2127: 
1.1       root     2128: SAVEGAME MENU
1.1.1.2   root     2129: 
1.1       root     2130: =============================================================================
                   2131: */
                   2132: static menuframework_s s_savegame_menu;
                   2133: static menuaction_s            s_savegame_actions[MAX_SAVEGAMES];
1.1.1.2   root     2134: 
1.1       root     2135: void SaveGameCallback( void *self )
                   2136: {
                   2137:        menuaction_s *a = ( menuaction_s * ) self;
1.1.1.2   root     2138: 
1.1       root     2139:        Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] ));
                   2140:        M_ForceMenuOff ();
                   2141: }
1.1.1.2   root     2142: 
1.1       root     2143: void SaveGame_MenuDraw( void )
                   2144: {
                   2145:        M_Banner( "m_banner_save_game" );
                   2146:        Menu_AdjustCursor( &s_savegame_menu, 1 );
                   2147:        Menu_Draw( &s_savegame_menu );
                   2148: }
1.1.1.2   root     2149: 
1.1       root     2150: void SaveGame_MenuInit( void )
                   2151: {
                   2152:        int i;
1.1.1.2   root     2153: 
1.1       root     2154:        s_savegame_menu.x = viddef.width / 2 - 120;
                   2155:        s_savegame_menu.y = viddef.height / 2 - 58;
                   2156:        s_savegame_menu.nitems = 0;
1.1.1.2   root     2157: 
1.1       root     2158:        Create_Savestrings();
1.1.1.2   root     2159: 
1.1       root     2160:        // don't include the autosave slot
                   2161:        for ( i = 0; i < MAX_SAVEGAMES-1; i++ )
                   2162:        {
                   2163:                s_savegame_actions[i].generic.name = m_savestrings[i+1];
                   2164:                s_savegame_actions[i].generic.localdata[0] = i+1;
                   2165:                s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
                   2166:                s_savegame_actions[i].generic.callback = SaveGameCallback;
1.1.1.2   root     2167: 
1.1       root     2168:                s_savegame_actions[i].generic.x = 0;
                   2169:                s_savegame_actions[i].generic.y = ( i ) * 10;
1.1.1.2   root     2170: 
1.1       root     2171:                s_savegame_actions[i].generic.type = MTYPE_ACTION;
1.1.1.2   root     2172: 
1.1       root     2173:                Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] );
                   2174:        }
                   2175: }
1.1.1.2   root     2176: 
1.1       root     2177: const char *SaveGame_MenuKey( int key )
                   2178: {
                   2179:        if ( key == K_ENTER || key == K_ESCAPE )
                   2180:        {
                   2181:                s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
                   2182:                if ( s_loadgame_menu.cursor < 0 )
                   2183:                        s_loadgame_menu.cursor = 0;
                   2184:        }
                   2185:        return Default_MenuKey( &s_savegame_menu, key );
                   2186: }
1.1.1.2   root     2187: 
1.1       root     2188: void M_Menu_SaveGame_f (void)
                   2189: {
                   2190:        if (!Com_ServerState())
                   2191:                return;         // not playing a game
1.1.1.2   root     2192: 
1.1       root     2193:        SaveGame_MenuInit();
                   2194:        M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey );
                   2195:        Create_Savestrings ();
                   2196: }
1.1.1.2   root     2197: 
                   2198: 
1.1       root     2199: /*
                   2200: =============================================================================
1.1.1.2   root     2201: 
1.1       root     2202: JOIN SERVER MENU
1.1.1.2   root     2203: 
1.1       root     2204: =============================================================================
                   2205: */
                   2206: #define MAX_LOCAL_SERVERS 8
1.1.1.2   root     2207: 
1.1       root     2208: static menuframework_s s_joinserver_menu;
                   2209: static menuseparator_s s_joinserver_server_title;
                   2210: static menuaction_s            s_joinserver_search_action;
                   2211: static menuaction_s            s_joinserver_address_book_action;
                   2212: static menuaction_s            s_joinserver_server_actions[MAX_LOCAL_SERVERS];
                   2213: 
                   2214: int            m_num_servers;
                   2215: #define        NO_SERVER_STRING        "<no server>"
                   2216: 
                   2217: // user readable information
                   2218: static char local_server_names[MAX_LOCAL_SERVERS][80];
                   2219: 
                   2220: // network address
                   2221: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS];
                   2222: 
                   2223: void M_AddToServerList (netadr_t adr, char *info)
                   2224: {
                   2225:        int             i;
                   2226: 
                   2227:        if (m_num_servers == MAX_LOCAL_SERVERS)
                   2228:                return;
                   2229:        while ( *info == ' ' )
                   2230:                info++;
                   2231: 
                   2232:        // ignore if duplicated
                   2233:        for (i=0 ; i<m_num_servers ; i++)
                   2234:                if (!strcmp(info, local_server_names[i]))
                   2235:                        return;
                   2236: 
                   2237:        local_server_netadr[m_num_servers] = adr;
                   2238:        strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
                   2239:        m_num_servers++;
                   2240: }
                   2241: 
1.1.1.2   root     2242: 
1.1       root     2243: void JoinServerFunc( void *self )
                   2244: {
                   2245:        char    buffer[128];
                   2246:        int             index;
                   2247: 
                   2248:        index = ( menuaction_s * ) self - s_joinserver_server_actions;
                   2249: 
                   2250:        if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 )
                   2251:                return;
                   2252: 
                   2253:        if (index >= m_num_servers)
                   2254:                return;
                   2255: 
                   2256:        Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index]));
                   2257:        Cbuf_AddText (buffer);
                   2258:        M_ForceMenuOff ();
                   2259: }
1.1.1.2   root     2260: 
1.1       root     2261: void AddressBookFunc( void *self )
                   2262: {
                   2263:        M_Menu_AddressBook_f();
                   2264: }
1.1.1.2   root     2265: 
1.1       root     2266: void NullCursorDraw( void *self )
                   2267: {
                   2268: }
                   2269: 
                   2270: void SearchLocalGames( void )
                   2271: {
                   2272:        int             i;
                   2273: 
                   2274:        m_num_servers = 0;
                   2275:        for (i=0 ; i<MAX_LOCAL_SERVERS ; i++)
                   2276:                strcpy (local_server_names[i], NO_SERVER_STRING);
                   2277: 
                   2278:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
                   2279:        M_Print( 16 + 16, 120 - 48 + 8,  "Searching for local servers, this" );
                   2280:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
                   2281:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
                   2282: 
                   2283:        // the text box won't show up unless we do a buffer swap
                   2284:        re.EndFrame();
                   2285: 
                   2286:        // send out info packets
                   2287:        CL_PingServers_f();
                   2288: }
1.1.1.2   root     2289: 
1.1       root     2290: void SearchLocalGamesFunc( void *self )
                   2291: {
                   2292:        SearchLocalGames();
                   2293: }
1.1.1.2   root     2294: 
1.1       root     2295: void JoinServer_MenuInit( void )
                   2296: {
                   2297:        int i;
1.1.1.2   root     2298: 
1.1       root     2299:        s_joinserver_menu.x = viddef.width * 0.50 - 120;
                   2300:        s_joinserver_menu.nitems = 0;
1.1.1.2   root     2301: 
1.1       root     2302:        s_joinserver_address_book_action.generic.type   = MTYPE_ACTION;
                   2303:        s_joinserver_address_book_action.generic.name   = "address book";
                   2304:        s_joinserver_address_book_action.generic.flags  = QMF_LEFT_JUSTIFY;
                   2305:        s_joinserver_address_book_action.generic.x              = 0;
                   2306:        s_joinserver_address_book_action.generic.y              = 0;
                   2307:        s_joinserver_address_book_action.generic.callback = AddressBookFunc;
1.1.1.2   root     2308: 
1.1       root     2309:        s_joinserver_search_action.generic.type = MTYPE_ACTION;
                   2310:        s_joinserver_search_action.generic.name = "refresh server list";
                   2311:        s_joinserver_search_action.generic.flags        = QMF_LEFT_JUSTIFY;
                   2312:        s_joinserver_search_action.generic.x    = 0;
                   2313:        s_joinserver_search_action.generic.y    = 10;
                   2314:        s_joinserver_search_action.generic.callback = SearchLocalGamesFunc;
                   2315:        s_joinserver_search_action.generic.statusbar = "search for servers";
1.1.1.2   root     2316: 
1.1       root     2317:        s_joinserver_server_title.generic.type = MTYPE_SEPARATOR;
                   2318:        s_joinserver_server_title.generic.name = "connect to...";
                   2319:        s_joinserver_server_title.generic.x    = 80;
                   2320:        s_joinserver_server_title.generic.y        = 30;
1.1.1.2   root     2321: 
1.1       root     2322:        for ( i = 0; i < MAX_LOCAL_SERVERS; i++ )
                   2323:        {
                   2324:                s_joinserver_server_actions[i].generic.type     = MTYPE_ACTION;
                   2325:                strcpy (local_server_names[i], NO_SERVER_STRING);
                   2326:                s_joinserver_server_actions[i].generic.name     = local_server_names[i];
                   2327:                s_joinserver_server_actions[i].generic.flags    = QMF_LEFT_JUSTIFY;
                   2328:                s_joinserver_server_actions[i].generic.x                = 0;
                   2329:                s_joinserver_server_actions[i].generic.y                = 40 + i*10;
                   2330:                s_joinserver_server_actions[i].generic.callback = JoinServerFunc;
                   2331:                s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect";
                   2332:        }
1.1.1.2   root     2333: 
1.1       root     2334:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action );
                   2335:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title );
                   2336:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action );
1.1.1.2   root     2337: 
1.1       root     2338:        for ( i = 0; i < 8; i++ )
                   2339:                Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] );
1.1.1.2   root     2340: 
1.1       root     2341:        Menu_Center( &s_joinserver_menu );
                   2342: 
                   2343:        SearchLocalGames();
                   2344: }
1.1.1.2   root     2345: 
1.1       root     2346: void JoinServer_MenuDraw(void)
                   2347: {
                   2348:        M_Banner( "m_banner_join_server" );
                   2349:        Menu_Draw( &s_joinserver_menu );
                   2350: }
1.1.1.2   root     2351: 
                   2352: 
1.1       root     2353: const char *JoinServer_MenuKey( int key )
                   2354: {
                   2355:        return Default_MenuKey( &s_joinserver_menu, key );
                   2356: }
1.1.1.2   root     2357: 
1.1       root     2358: void M_Menu_JoinServer_f (void)
                   2359: {
                   2360:        JoinServer_MenuInit();
                   2361:        M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey );
                   2362: }
                   2363: 
1.1.1.2   root     2364: 
1.1       root     2365: /*
                   2366: =============================================================================
1.1.1.2   root     2367: 
1.1       root     2368: START SERVER MENU
1.1.1.2   root     2369: 
1.1       root     2370: =============================================================================
                   2371: */
                   2372: static menuframework_s s_startserver_menu;
                   2373: static char **mapnames;
                   2374: static int       nummaps;
1.1.1.2   root     2375: 
1.1       root     2376: static menuaction_s    s_startserver_start_action;
                   2377: static menuaction_s    s_startserver_dmoptions_action;
                   2378: static menufield_s     s_timelimit_field;
                   2379: static menufield_s     s_fraglimit_field;
                   2380: static menufield_s     s_maxclients_field;
                   2381: static menufield_s     s_hostname_field;
                   2382: static menulist_s      s_startmap_list;
                   2383: static menulist_s      s_rules_box;
                   2384: 
                   2385: void DMOptionsFunc( void *self )
                   2386: {
                   2387:        if (s_rules_box.curvalue == 1)
                   2388:                return;
                   2389:        M_Menu_DMOptions_f();
                   2390: }
                   2391: 
                   2392: void RulesChangeFunc ( void *self )
                   2393: {
                   2394:        // DM
                   2395:        if (s_rules_box.curvalue == 0)
                   2396:        {
                   2397:                s_maxclients_field.generic.statusbar = NULL;
                   2398:                s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2399:        }
1.1.1.3   root     2400:        else if(s_rules_box.curvalue == 1)              // coop                         // PGM
1.1       root     2401:        {
                   2402:                s_maxclients_field.generic.statusbar = "4 maximum for cooperative";
                   2403:                if (atoi(s_maxclients_field.buffer) > 4)
                   2404:                        strcpy( s_maxclients_field.buffer, "4" );
                   2405:                s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative";
                   2406:        }
1.1.1.3   root     2407: //=====
                   2408: //PGM
                   2409:        // ROGUE GAMES
                   2410:        else if(Developer_searchpath(2) == 2)
                   2411:        {
                   2412:                if (s_rules_box.curvalue == 2)                  // tag  
                   2413:                {
                   2414:                        s_maxclients_field.generic.statusbar = NULL;
                   2415:                        s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2416:                }
                   2417: /*
                   2418:                else if(s_rules_box.curvalue == 3)              // deathball
                   2419:                {
                   2420:                        s_maxclients_field.generic.statusbar = NULL;
                   2421:                        s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2422:                }
                   2423: */
                   2424:        }
                   2425: //PGM
                   2426: //=====
1.1       root     2427: }
1.1.1.2   root     2428: 
1.1       root     2429: void StartServerActionFunc( void *self )
                   2430: {
                   2431:        char    startmap[1024];
                   2432:        int             timelimit;
                   2433:        int             fraglimit;
                   2434:        int             maxclients;
                   2435:        char    *spot;
1.1.1.2   root     2436: 
1.1       root     2437:        strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
                   2438: 
                   2439:        maxclients  = atoi( s_maxclients_field.buffer );
                   2440:        timelimit       = atoi( s_timelimit_field.buffer );
                   2441:        fraglimit       = atoi( s_fraglimit_field.buffer );
                   2442: 
                   2443:        Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) );
                   2444:        Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) );
                   2445:        Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) );
                   2446:        Cvar_Set("hostname", s_hostname_field.buffer );
1.1.1.3   root     2447: //     Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
                   2448: //     Cvar_SetValue ("coop", s_rules_box.curvalue );
                   2449: 
                   2450: //PGM
                   2451:        if((s_rules_box.curvalue < 2) || (Developer_searchpath(2) != 2))
                   2452:        {
                   2453:                Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
                   2454:                Cvar_SetValue ("coop", s_rules_box.curvalue );
                   2455:                Cvar_SetValue ("gamerules", 0 );
                   2456:        }
                   2457:        else
                   2458:        {
                   2459:                Cvar_SetValue ("deathmatch", 1 );       // deathmatch is always true for rogue games, right?
                   2460:                Cvar_SetValue ("coop", 0 );                     // FIXME - this might need to depend on which game we're running
                   2461:                Cvar_SetValue ("gamerules", s_rules_box.curvalue );
                   2462:        }
                   2463: //PGM
1.1       root     2464: 
                   2465:        spot = NULL;
1.1.1.3   root     2466:        if (s_rules_box.curvalue == 1)          // PGM
1.1       root     2467:        {
1.1.1.2   root     2468:                if(Q_stricmp(startmap, "bunk1") == 0)
                   2469:                        spot = "start";
                   2470:                else if(Q_stricmp(startmap, "mintro") == 0)
                   2471:                        spot = "start";
                   2472:                else if(Q_stricmp(startmap, "fact1") == 0)
                   2473:                        spot = "start";
                   2474:                else if(Q_stricmp(startmap, "power1") == 0)
                   2475:                        spot = "pstart";
                   2476:                else if(Q_stricmp(startmap, "biggun") == 0)
                   2477:                        spot = "bstart";
                   2478:                else if(Q_stricmp(startmap, "hangar1") == 0)
                   2479:                        spot = "unitstart";
                   2480:                else if(Q_stricmp(startmap, "city1") == 0)
                   2481:                        spot = "unitstart";
                   2482:                else if(Q_stricmp(startmap, "boss1") == 0)
1.1.1.3   root     2483:                        spot = "bosstart";
1.1       root     2484:        }
                   2485: 
                   2486:        if (spot)
                   2487:        {
                   2488:                if (Com_ServerState())
                   2489:                        Cbuf_AddText ("disconnect\n");
                   2490:                Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot));
                   2491:        }
                   2492:        else
                   2493:        {
                   2494:                Cbuf_AddText (va("map %s\n", startmap));
                   2495:        }
                   2496: 
                   2497:        M_ForceMenuOff ();
                   2498: }
                   2499: 
                   2500: void StartServer_MenuInit( void )
                   2501: {
                   2502:        static const char *dm_coop_names[] =
                   2503:        {
                   2504:                "deathmatch",
                   2505:                "cooperative",
                   2506:                0
                   2507:        };
1.1.1.3   root     2508: //=======
                   2509: //PGM
                   2510:        static const char *dm_coop_names_rogue[] =
                   2511:        {
                   2512:                "deathmatch",
                   2513:                "cooperative",
                   2514:                "tag",
                   2515: //             "deathball",
                   2516:                0
                   2517:        };
                   2518: //PGM
                   2519: //=======
1.1       root     2520:        char *buffer;
                   2521:        char  mapsname[1024];
                   2522:        char *s;
                   2523:        int length;
                   2524:        int i;
                   2525:        FILE *fp;
                   2526: 
                   2527:        /*
                   2528:        ** load the list of map names
                   2529:        */
                   2530:        Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() );
                   2531:        if ( ( fp = fopen( mapsname, "rb" ) ) == 0 )
                   2532:        {
                   2533:                if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 )
                   2534:                        Com_Error( ERR_DROP, "couldn't find maps.lst\n" );
                   2535:        }
                   2536:        else
                   2537:        {
1.1.1.2   root     2538: #ifdef _WIN32
1.1       root     2539:                length = filelength( fileno( fp  ) );
1.1.1.2   root     2540: #else
                   2541:                fseek(fp, 0, SEEK_END);
                   2542:                length = ftell(fp);
                   2543:                fseek(fp, 0, SEEK_SET);
                   2544: #endif
1.1       root     2545:                buffer = malloc( length );
                   2546:                fread( buffer, length, 1, fp );
                   2547:        }
                   2548: 
                   2549:        s = buffer;
                   2550: 
                   2551:        i = 0;
                   2552:        while ( i < length )
                   2553:        {
                   2554:                if ( s[i] == '\r' )
                   2555:                        nummaps++;
                   2556:                i++;
                   2557:        }
                   2558: 
                   2559:        if ( nummaps == 0 )
                   2560:                Com_Error( ERR_DROP, "no maps in maps.lst\n" );
                   2561: 
                   2562:        mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) );
                   2563:        memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) );
                   2564: 
                   2565:        s = buffer;
                   2566: 
                   2567:        for ( i = 0; i < nummaps; i++ )
                   2568:        {
                   2569:     char  shortname[MAX_TOKEN_CHARS];
                   2570:     char  longname[MAX_TOKEN_CHARS];
                   2571:                char  scratch[200];
                   2572:                int             j, l;
                   2573: 
                   2574:                strcpy( shortname, COM_Parse( &s ) );
                   2575:                l = strlen(shortname);
                   2576:                for (j=0 ; j<l ; j++)
                   2577:                        shortname[j] = toupper(shortname[j]);
                   2578:                strcpy( longname, COM_Parse( &s ) );
                   2579:                Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname );
                   2580: 
                   2581:                mapnames[i] = malloc( strlen( scratch ) + 1 );
                   2582:                strcpy( mapnames[i], scratch );
                   2583:        }
                   2584:        mapnames[nummaps] = 0;
                   2585: 
                   2586:        if ( fp != 0 )
                   2587:        {
                   2588:                fp = 0;
                   2589:                free( buffer );
                   2590:        }
                   2591:        else
                   2592:        {
                   2593:                FS_FreeFile( buffer );
                   2594:        }
                   2595: 
                   2596:        /*
                   2597:        ** initialize the menu stuff
                   2598:        */
                   2599:        s_startserver_menu.x = viddef.width * 0.50;
                   2600:        s_startserver_menu.nitems = 0;
1.1.1.2   root     2601: 
1.1       root     2602:        s_startmap_list.generic.type = MTYPE_SPINCONTROL;
                   2603:        s_startmap_list.generic.x       = 0;
                   2604:        s_startmap_list.generic.y       = 0;
                   2605:        s_startmap_list.generic.name    = "initial map";
                   2606:        s_startmap_list.itemnames = mapnames;
1.1.1.2   root     2607: 
1.1       root     2608:        s_rules_box.generic.type = MTYPE_SPINCONTROL;
                   2609:        s_rules_box.generic.x   = 0;
                   2610:        s_rules_box.generic.y   = 20;
                   2611:        s_rules_box.generic.name        = "rules";
1.1.1.3   root     2612:        
                   2613: //PGM - rogue games only available with rogue DLL.
                   2614:        if(Developer_searchpath(2) == 2)
                   2615:                s_rules_box.itemnames = dm_coop_names_rogue;
                   2616:        else
                   2617:                s_rules_box.itemnames = dm_coop_names;
                   2618: //PGM
                   2619: 
1.1       root     2620:        if (Cvar_VariableValue("coop"))
                   2621:                s_rules_box.curvalue = 1;
                   2622:        else
                   2623:                s_rules_box.curvalue = 0;
                   2624:        s_rules_box.generic.callback = RulesChangeFunc;
1.1.1.2   root     2625: 
1.1       root     2626:        s_timelimit_field.generic.type = MTYPE_FIELD;
                   2627:        s_timelimit_field.generic.name = "time limit";
                   2628:        s_timelimit_field.generic.flags = QMF_NUMBERSONLY;
                   2629:        s_timelimit_field.generic.x     = 0;
                   2630:        s_timelimit_field.generic.y     = 36;
                   2631:        s_timelimit_field.generic.statusbar = "0 = no limit";
                   2632:        s_timelimit_field.length = 3;
                   2633:        s_timelimit_field.visible_length = 3;
                   2634:        strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") );
1.1.1.2   root     2635: 
1.1       root     2636:        s_fraglimit_field.generic.type = MTYPE_FIELD;
                   2637:        s_fraglimit_field.generic.name = "frag limit";
                   2638:        s_fraglimit_field.generic.flags = QMF_NUMBERSONLY;
                   2639:        s_fraglimit_field.generic.x     = 0;
                   2640:        s_fraglimit_field.generic.y     = 54;
                   2641:        s_fraglimit_field.generic.statusbar = "0 = no limit";
                   2642:        s_fraglimit_field.length = 3;
                   2643:        s_fraglimit_field.visible_length = 3;
                   2644:        strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") );
                   2645: 
                   2646:        /*
                   2647:        ** maxclients determines the maximum number of players that can join
                   2648:        ** the game.  If maxclients is only "1" then we should default the menu
                   2649:        ** option to 8 players, otherwise use whatever its current value is. 
                   2650:        ** Clamping will be done when the server is actually started.
                   2651:        */
                   2652:        s_maxclients_field.generic.type = MTYPE_FIELD;
                   2653:        s_maxclients_field.generic.name = "max players";
                   2654:        s_maxclients_field.generic.flags = QMF_NUMBERSONLY;
                   2655:        s_maxclients_field.generic.x    = 0;
                   2656:        s_maxclients_field.generic.y    = 72;
                   2657:        s_maxclients_field.generic.statusbar = NULL;
                   2658:        s_maxclients_field.length = 3;
                   2659:        s_maxclients_field.visible_length = 3;
                   2660:        if ( Cvar_VariableValue( "maxclients" ) == 1 )
                   2661:                strcpy( s_maxclients_field.buffer, "8" );
                   2662:        else 
                   2663:                strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") );
                   2664: 
                   2665:        s_hostname_field.generic.type = MTYPE_FIELD;
                   2666:        s_hostname_field.generic.name = "hostname";
                   2667:        s_hostname_field.generic.flags = 0;
                   2668:        s_hostname_field.generic.x      = 0;
                   2669:        s_hostname_field.generic.y      = 90;
                   2670:        s_hostname_field.generic.statusbar = NULL;
                   2671:        s_hostname_field.length = 12;
                   2672:        s_hostname_field.visible_length = 12;
                   2673:        strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") );
                   2674: 
                   2675:        s_startserver_dmoptions_action.generic.type = MTYPE_ACTION;
                   2676:        s_startserver_dmoptions_action.generic.name     = " deathmatch flags";
                   2677:        s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY;
                   2678:        s_startserver_dmoptions_action.generic.x        = 24;
                   2679:        s_startserver_dmoptions_action.generic.y        = 108;
                   2680:        s_startserver_dmoptions_action.generic.statusbar = NULL;
                   2681:        s_startserver_dmoptions_action.generic.callback = DMOptionsFunc;
                   2682: 
                   2683:        s_startserver_start_action.generic.type = MTYPE_ACTION;
                   2684:        s_startserver_start_action.generic.name = " begin";
                   2685:        s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY;
                   2686:        s_startserver_start_action.generic.x    = 24;
                   2687:        s_startserver_start_action.generic.y    = 128;
                   2688:        s_startserver_start_action.generic.callback = StartServerActionFunc;
                   2689: 
                   2690:        Menu_AddItem( &s_startserver_menu, &s_startmap_list );
                   2691:        Menu_AddItem( &s_startserver_menu, &s_rules_box );
                   2692:        Menu_AddItem( &s_startserver_menu, &s_timelimit_field );
                   2693:        Menu_AddItem( &s_startserver_menu, &s_fraglimit_field );
                   2694:        Menu_AddItem( &s_startserver_menu, &s_maxclients_field );
                   2695:        Menu_AddItem( &s_startserver_menu, &s_hostname_field );
                   2696:        Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action );
                   2697:        Menu_AddItem( &s_startserver_menu, &s_startserver_start_action );
                   2698: 
                   2699:        Menu_Center( &s_startserver_menu );
                   2700: 
                   2701:        // call this now to set proper inital state
                   2702:        RulesChangeFunc ( NULL );
                   2703: }
1.1.1.2   root     2704: 
1.1       root     2705: void StartServer_MenuDraw(void)
                   2706: {
                   2707:        Menu_Draw( &s_startserver_menu );
                   2708: }
1.1.1.2   root     2709: 
1.1       root     2710: const char *StartServer_MenuKey( int key )
                   2711: {
                   2712:        if ( key == K_ESCAPE )
                   2713:        {
                   2714:                if ( mapnames )
                   2715:                {
                   2716:                        int i;
                   2717: 
                   2718:                        for ( i = 0; i < nummaps; i++ )
                   2719:                                free( mapnames[i] );
                   2720:                        free( mapnames );
                   2721:                }
                   2722:                mapnames = 0;
                   2723:                nummaps = 0;
                   2724:        }
1.1.1.2   root     2725: 
1.1       root     2726:        return Default_MenuKey( &s_startserver_menu, key );
                   2727: }
1.1.1.2   root     2728: 
1.1       root     2729: void M_Menu_StartServer_f (void)
                   2730: {
                   2731:        StartServer_MenuInit();
                   2732:        M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey );
                   2733: }
1.1.1.2   root     2734: 
1.1       root     2735: /*
                   2736: =============================================================================
                   2737: 
                   2738: DMOPTIONS BOOK MENU
                   2739: 
                   2740: =============================================================================
                   2741: */
                   2742: static char dmoptions_statusbar[128];
                   2743: 
                   2744: static menuframework_s s_dmoptions_menu;
                   2745: 
                   2746: static menulist_s      s_friendlyfire_box;
                   2747: static menulist_s      s_falls_box;
                   2748: static menulist_s      s_weapons_stay_box;
                   2749: static menulist_s      s_instant_powerups_box;
                   2750: static menulist_s      s_powerups_box;
                   2751: static menulist_s      s_health_box;
                   2752: static menulist_s      s_spawn_farthest_box;
                   2753: static menulist_s      s_teamplay_box;
                   2754: static menulist_s      s_samelevel_box;
                   2755: static menulist_s      s_force_respawn_box;
                   2756: static menulist_s      s_armor_box;
                   2757: static menulist_s      s_allow_exit_box;
                   2758: static menulist_s      s_infinite_ammo_box;
                   2759: static menulist_s      s_fixed_fov_box;
                   2760: static menulist_s      s_quad_drop_box;
                   2761: 
1.1.1.3   root     2762: //ROGUE
                   2763: static menulist_s      s_no_mines_box;
                   2764: static menulist_s      s_no_nukes_box;
                   2765: static menulist_s      s_stack_double_box;
                   2766: static menulist_s      s_no_spheres_box;
                   2767: //ROGUE
                   2768: 
1.1       root     2769: static void DMFlagCallback( void *self )
                   2770: {
                   2771:        menulist_s *f = ( menulist_s * ) self;
                   2772:        int flags;
                   2773:        int bit = 0;
                   2774: 
                   2775:        flags = Cvar_VariableValue( "dmflags" );
                   2776: 
                   2777:        if ( f == &s_friendlyfire_box )
                   2778:        {
                   2779:                if ( f->curvalue )
                   2780:                        flags &= ~DF_NO_FRIENDLY_FIRE;
                   2781:                else
                   2782:                        flags |= DF_NO_FRIENDLY_FIRE;
                   2783:                goto setvalue;
                   2784:        }
                   2785:        else if ( f == &s_falls_box )
                   2786:        {
                   2787:                if ( f->curvalue )
                   2788:                        flags &= ~DF_NO_FALLING;
                   2789:                else
                   2790:                        flags |= DF_NO_FALLING;
                   2791:                goto setvalue;
                   2792:        }
                   2793:        else if ( f == &s_weapons_stay_box ) 
                   2794:        {
                   2795:                bit = DF_WEAPONS_STAY;
                   2796:        }
                   2797:        else if ( f == &s_instant_powerups_box )
                   2798:        {
                   2799:                bit = DF_INSTANT_ITEMS;
                   2800:        }
                   2801:        else if ( f == &s_allow_exit_box )
                   2802:        {
                   2803:                bit = DF_ALLOW_EXIT;
                   2804:        }
                   2805:        else if ( f == &s_powerups_box )
                   2806:        {
                   2807:                if ( f->curvalue )
                   2808:                        flags &= ~DF_NO_ITEMS;
                   2809:                else
                   2810:                        flags |= DF_NO_ITEMS;
                   2811:                goto setvalue;
                   2812:        }
                   2813:        else if ( f == &s_health_box )
                   2814:        {
                   2815:                if ( f->curvalue )
                   2816:                        flags &= ~DF_NO_HEALTH;
                   2817:                else
                   2818:                        flags |= DF_NO_HEALTH;
                   2819:                goto setvalue;
                   2820:        }
                   2821:        else if ( f == &s_spawn_farthest_box )
                   2822:        {
                   2823:                bit = DF_SPAWN_FARTHEST;
                   2824:        }
                   2825:        else if ( f == &s_teamplay_box )
                   2826:        {
                   2827:                if ( f->curvalue == 1 )
                   2828:                {
                   2829:                        flags |=  DF_SKINTEAMS;
                   2830:                        flags &= ~DF_MODELTEAMS;
                   2831:                }
                   2832:                else if ( f->curvalue == 2 )
                   2833:                {
                   2834:                        flags |=  DF_MODELTEAMS;
                   2835:                        flags &= ~DF_SKINTEAMS;
                   2836:                }
                   2837:                else
                   2838:                {
                   2839:                        flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS );
                   2840:                }
                   2841: 
                   2842:                goto setvalue;
                   2843:        }
                   2844:        else if ( f == &s_samelevel_box )
                   2845:        {
                   2846:                bit = DF_SAME_LEVEL;
                   2847:        }
                   2848:        else if ( f == &s_force_respawn_box )
                   2849:        {
                   2850:                bit = DF_FORCE_RESPAWN;
                   2851:        }
                   2852:        else if ( f == &s_armor_box )
                   2853:        {
                   2854:                if ( f->curvalue )
                   2855:                        flags &= ~DF_NO_ARMOR;
                   2856:                else
                   2857:                        flags |= DF_NO_ARMOR;
                   2858:                goto setvalue;
                   2859:        }
                   2860:        else if ( f == &s_infinite_ammo_box )
                   2861:        {
                   2862:                bit = DF_INFINITE_AMMO;
                   2863:        }
                   2864:        else if ( f == &s_fixed_fov_box )
                   2865:        {
                   2866:                bit = DF_FIXED_FOV;
                   2867:        }
                   2868:        else if ( f == &s_quad_drop_box )
                   2869:        {
                   2870:                bit = DF_QUAD_DROP;
                   2871:        }
                   2872: 
1.1.1.3   root     2873: //=======
                   2874: //ROGUE
                   2875:        else if (Developer_searchpath(2) == 2)
                   2876:        {
                   2877:                if ( f == &s_no_mines_box)
                   2878:                {
                   2879:                        bit = DF_NO_MINES;
                   2880:                }
                   2881:                else if ( f == &s_no_nukes_box)
                   2882:                {
                   2883:                        bit = DF_NO_NUKES;
                   2884:                }
                   2885:                else if ( f == &s_stack_double_box)
                   2886:                {
                   2887:                        bit = DF_NO_STACK_DOUBLE;
                   2888:                }
                   2889:                else if ( f == &s_no_spheres_box)
                   2890:                {
                   2891:                        bit = DF_NO_SPHERES;
                   2892:                }
                   2893:        }
                   2894: //ROGUE
                   2895: //=======
1.1       root     2896: 
                   2897:        if ( f )
                   2898:        {
                   2899:                if ( f->curvalue == 0 )
                   2900:                        flags &= ~bit;
                   2901:                else
                   2902:                        flags |= bit;
                   2903:        }
                   2904: 
                   2905: setvalue:
                   2906:        Cvar_SetValue ("dmflags", flags);
                   2907: 
                   2908:        Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags );
                   2909: 
                   2910: }
                   2911: 
                   2912: void DMOptions_MenuInit( void )
                   2913: {
                   2914:        static const char *yes_no_names[] =
                   2915:        {
                   2916:                "no", "yes", 0
                   2917:        };
                   2918:        static const char *teamplay_names[] = 
                   2919:        {
                   2920:                "disabled", "by skin", "by model", 0
                   2921:        };
                   2922:        int dmflags = Cvar_VariableValue( "dmflags" );
                   2923:        int y = 0;
                   2924: 
                   2925:        s_dmoptions_menu.x = viddef.width * 0.50;
                   2926:        s_dmoptions_menu.nitems = 0;
                   2927: 
                   2928:        s_falls_box.generic.type = MTYPE_SPINCONTROL;
                   2929:        s_falls_box.generic.x   = 0;
                   2930:        s_falls_box.generic.y   = y;
                   2931:        s_falls_box.generic.name        = "falling damage";
                   2932:        s_falls_box.generic.callback = DMFlagCallback;
                   2933:        s_falls_box.itemnames = yes_no_names;
                   2934:        s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0;
                   2935: 
                   2936:        s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL;
                   2937:        s_weapons_stay_box.generic.x    = 0;
                   2938:        s_weapons_stay_box.generic.y    = y += 10;
                   2939:        s_weapons_stay_box.generic.name = "weapons stay";
                   2940:        s_weapons_stay_box.generic.callback = DMFlagCallback;
                   2941:        s_weapons_stay_box.itemnames = yes_no_names;
                   2942:        s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0;
                   2943: 
                   2944:        s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL;
                   2945:        s_instant_powerups_box.generic.x        = 0;
                   2946:        s_instant_powerups_box.generic.y        = y += 10;
                   2947:        s_instant_powerups_box.generic.name     = "instant powerups";
                   2948:        s_instant_powerups_box.generic.callback = DMFlagCallback;
                   2949:        s_instant_powerups_box.itemnames = yes_no_names;
                   2950:        s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0;
                   2951: 
                   2952:        s_powerups_box.generic.type = MTYPE_SPINCONTROL;
                   2953:        s_powerups_box.generic.x        = 0;
                   2954:        s_powerups_box.generic.y        = y += 10;
                   2955:        s_powerups_box.generic.name     = "allow powerups";
                   2956:        s_powerups_box.generic.callback = DMFlagCallback;
                   2957:        s_powerups_box.itemnames = yes_no_names;
                   2958:        s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0;
                   2959: 
                   2960:        s_health_box.generic.type = MTYPE_SPINCONTROL;
                   2961:        s_health_box.generic.x  = 0;
                   2962:        s_health_box.generic.y  = y += 10;
                   2963:        s_health_box.generic.callback = DMFlagCallback;
                   2964:        s_health_box.generic.name       = "allow health";
                   2965:        s_health_box.itemnames = yes_no_names;
                   2966:        s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0;
                   2967: 
                   2968:        s_armor_box.generic.type = MTYPE_SPINCONTROL;
                   2969:        s_armor_box.generic.x   = 0;
                   2970:        s_armor_box.generic.y   = y += 10;
                   2971:        s_armor_box.generic.name        = "allow armor";
                   2972:        s_armor_box.generic.callback = DMFlagCallback;
                   2973:        s_armor_box.itemnames = yes_no_names;
                   2974:        s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0;
                   2975: 
                   2976:        s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL;
                   2977:        s_spawn_farthest_box.generic.x  = 0;
                   2978:        s_spawn_farthest_box.generic.y  = y += 10;
                   2979:        s_spawn_farthest_box.generic.name       = "spawn farthest";
                   2980:        s_spawn_farthest_box.generic.callback = DMFlagCallback;
                   2981:        s_spawn_farthest_box.itemnames = yes_no_names;
                   2982:        s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0;
                   2983: 
                   2984:        s_samelevel_box.generic.type = MTYPE_SPINCONTROL;
                   2985:        s_samelevel_box.generic.x       = 0;
                   2986:        s_samelevel_box.generic.y       = y += 10;
                   2987:        s_samelevel_box.generic.name    = "same map";
                   2988:        s_samelevel_box.generic.callback = DMFlagCallback;
                   2989:        s_samelevel_box.itemnames = yes_no_names;
                   2990:        s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0;
                   2991: 
                   2992:        s_force_respawn_box.generic.type = MTYPE_SPINCONTROL;
                   2993:        s_force_respawn_box.generic.x   = 0;
                   2994:        s_force_respawn_box.generic.y   = y += 10;
                   2995:        s_force_respawn_box.generic.name        = "force respawn";
                   2996:        s_force_respawn_box.generic.callback = DMFlagCallback;
                   2997:        s_force_respawn_box.itemnames = yes_no_names;
                   2998:        s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0;
                   2999: 
                   3000:        s_teamplay_box.generic.type = MTYPE_SPINCONTROL;
                   3001:        s_teamplay_box.generic.x        = 0;
                   3002:        s_teamplay_box.generic.y        = y += 10;
                   3003:        s_teamplay_box.generic.name     = "teamplay";
                   3004:        s_teamplay_box.generic.callback = DMFlagCallback;
                   3005:        s_teamplay_box.itemnames = teamplay_names;
                   3006: 
                   3007:        s_allow_exit_box.generic.type = MTYPE_SPINCONTROL;
                   3008:        s_allow_exit_box.generic.x      = 0;
                   3009:        s_allow_exit_box.generic.y      = y += 10;
                   3010:        s_allow_exit_box.generic.name   = "allow exit";
                   3011:        s_allow_exit_box.generic.callback = DMFlagCallback;
                   3012:        s_allow_exit_box.itemnames = yes_no_names;
                   3013:        s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0;
                   3014: 
                   3015:        s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL;
                   3016:        s_infinite_ammo_box.generic.x   = 0;
                   3017:        s_infinite_ammo_box.generic.y   = y += 10;
                   3018:        s_infinite_ammo_box.generic.name        = "infinite ammo";
                   3019:        s_infinite_ammo_box.generic.callback = DMFlagCallback;
                   3020:        s_infinite_ammo_box.itemnames = yes_no_names;
                   3021:        s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0;
                   3022: 
                   3023:        s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL;
                   3024:        s_fixed_fov_box.generic.x       = 0;
                   3025:        s_fixed_fov_box.generic.y       = y += 10;
                   3026:        s_fixed_fov_box.generic.name    = "fixed FOV";
                   3027:        s_fixed_fov_box.generic.callback = DMFlagCallback;
                   3028:        s_fixed_fov_box.itemnames = yes_no_names;
                   3029:        s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0;
                   3030: 
                   3031:        s_quad_drop_box.generic.type = MTYPE_SPINCONTROL;
                   3032:        s_quad_drop_box.generic.x       = 0;
                   3033:        s_quad_drop_box.generic.y       = y += 10;
                   3034:        s_quad_drop_box.generic.name    = "quad drop";
                   3035:        s_quad_drop_box.generic.callback = DMFlagCallback;
                   3036:        s_quad_drop_box.itemnames = yes_no_names;
                   3037:        s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0;
                   3038: 
                   3039:        s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL;
                   3040:        s_friendlyfire_box.generic.x    = 0;
                   3041:        s_friendlyfire_box.generic.y    = y += 10;
                   3042:        s_friendlyfire_box.generic.name = "friendly fire";
                   3043:        s_friendlyfire_box.generic.callback = DMFlagCallback;
                   3044:        s_friendlyfire_box.itemnames = yes_no_names;
                   3045:        s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0;
                   3046: 
1.1.1.3   root     3047: //============
                   3048: //ROGUE
                   3049:        if(Developer_searchpath(2) == 2)
                   3050:        {
                   3051:                s_no_mines_box.generic.type = MTYPE_SPINCONTROL;
                   3052:                s_no_mines_box.generic.x        = 0;
                   3053:                s_no_mines_box.generic.y        = y += 10;
                   3054:                s_no_mines_box.generic.name     = "remove mines";
                   3055:                s_no_mines_box.generic.callback = DMFlagCallback;
                   3056:                s_no_mines_box.itemnames = yes_no_names;
                   3057:                s_no_mines_box.curvalue = ( dmflags & DF_NO_MINES ) != 0;
                   3058: 
                   3059:                s_no_nukes_box.generic.type = MTYPE_SPINCONTROL;
                   3060:                s_no_nukes_box.generic.x        = 0;
                   3061:                s_no_nukes_box.generic.y        = y += 10;
                   3062:                s_no_nukes_box.generic.name     = "remove nukes";
                   3063:                s_no_nukes_box.generic.callback = DMFlagCallback;
                   3064:                s_no_nukes_box.itemnames = yes_no_names;
                   3065:                s_no_nukes_box.curvalue = ( dmflags & DF_NO_NUKES ) != 0;
                   3066: 
                   3067:                s_stack_double_box.generic.type = MTYPE_SPINCONTROL;
                   3068:                s_stack_double_box.generic.x    = 0;
                   3069:                s_stack_double_box.generic.y    = y += 10;
                   3070:                s_stack_double_box.generic.name = "2x/4x stacking off";
                   3071:                s_stack_double_box.generic.callback = DMFlagCallback;
                   3072:                s_stack_double_box.itemnames = yes_no_names;
                   3073:                s_stack_double_box.curvalue = ( dmflags & DF_NO_STACK_DOUBLE ) != 0;
                   3074: 
                   3075:                s_no_spheres_box.generic.type = MTYPE_SPINCONTROL;
                   3076:                s_no_spheres_box.generic.x      = 0;
                   3077:                s_no_spheres_box.generic.y      = y += 10;
                   3078:                s_no_spheres_box.generic.name   = "remove spheres";
                   3079:                s_no_spheres_box.generic.callback = DMFlagCallback;
                   3080:                s_no_spheres_box.itemnames = yes_no_names;
                   3081:                s_no_spheres_box.curvalue = ( dmflags & DF_NO_SPHERES ) != 0;
                   3082: 
                   3083:        }
                   3084: //ROGUE
                   3085: //============
                   3086: 
1.1       root     3087:        Menu_AddItem( &s_dmoptions_menu, &s_falls_box );
                   3088:        Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box );
                   3089:        Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box );
                   3090:        Menu_AddItem( &s_dmoptions_menu, &s_powerups_box );
                   3091:        Menu_AddItem( &s_dmoptions_menu, &s_health_box );
                   3092:        Menu_AddItem( &s_dmoptions_menu, &s_armor_box );
                   3093:        Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box );
                   3094:        Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box );
                   3095:        Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box );
                   3096:        Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box );
                   3097:        Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box );
                   3098:        Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box );
                   3099:        Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box );
                   3100:        Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box );
                   3101:        Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box );
                   3102: 
1.1.1.3   root     3103: //=======
                   3104: //ROGUE
                   3105:        if(Developer_searchpath(2) == 2)
                   3106:        {
                   3107:                Menu_AddItem( &s_dmoptions_menu, &s_no_mines_box );
                   3108:                Menu_AddItem( &s_dmoptions_menu, &s_no_nukes_box );
                   3109:                Menu_AddItem( &s_dmoptions_menu, &s_stack_double_box );
                   3110:                Menu_AddItem( &s_dmoptions_menu, &s_no_spheres_box );
                   3111:        }
                   3112: //ROGUE
                   3113: //=======
                   3114: 
1.1       root     3115:        Menu_Center( &s_dmoptions_menu );
                   3116: 
                   3117:        // set the original dmflags statusbar
                   3118:        DMFlagCallback( 0 );
                   3119:        Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar );
                   3120: }
                   3121: 
                   3122: void DMOptions_MenuDraw(void)
                   3123: {
                   3124:        Menu_Draw( &s_dmoptions_menu );
                   3125: }
                   3126: 
                   3127: const char *DMOptions_MenuKey( int key )
                   3128: {
                   3129:        return Default_MenuKey( &s_dmoptions_menu, key );
                   3130: }
                   3131: 
                   3132: void M_Menu_DMOptions_f (void)
                   3133: {
                   3134:        DMOptions_MenuInit();
                   3135:        M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey );
                   3136: }
                   3137: 
                   3138: /*
                   3139: =============================================================================
1.1.1.2   root     3140: 
                   3141: DOWNLOADOPTIONS BOOK MENU
                   3142: 
                   3143: =============================================================================
                   3144: */
                   3145: static menuframework_s s_downloadoptions_menu;
                   3146: 
                   3147: static menuseparator_s s_download_title;
                   3148: static menulist_s      s_allow_download_box;
                   3149: static menulist_s      s_allow_download_maps_box;
                   3150: static menulist_s      s_allow_download_models_box;
                   3151: static menulist_s      s_allow_download_players_box;
                   3152: static menulist_s      s_allow_download_sounds_box;
                   3153: 
                   3154: static void DownloadCallback( void *self )
                   3155: {
                   3156:        menulist_s *f = ( menulist_s * ) self;
                   3157: 
                   3158:        if (f == &s_allow_download_box)
                   3159:        {
                   3160:                Cvar_SetValue("allow_download", f->curvalue);
                   3161:        }
                   3162: 
                   3163:        else if (f == &s_allow_download_maps_box)
                   3164:        {
                   3165:                Cvar_SetValue("allow_download_maps", f->curvalue);
                   3166:        }
                   3167: 
                   3168:        else if (f == &s_allow_download_models_box)
                   3169:        {
                   3170:                Cvar_SetValue("allow_download_models", f->curvalue);
                   3171:        }
                   3172: 
                   3173:        else if (f == &s_allow_download_players_box)
                   3174:        {
                   3175:                Cvar_SetValue("allow_download_players", f->curvalue);
                   3176:        }
                   3177: 
                   3178:        else if (f == &s_allow_download_sounds_box)
                   3179:        {
                   3180:                Cvar_SetValue("allow_download_sounds", f->curvalue);
                   3181:        }
                   3182: }
                   3183: 
                   3184: void DownloadOptions_MenuInit( void )
                   3185: {
                   3186:        static const char *yes_no_names[] =
                   3187:        {
                   3188:                "no", "yes", 0
                   3189:        };
                   3190:        int y = 0;
                   3191: 
                   3192:        s_downloadoptions_menu.x = viddef.width * 0.50;
                   3193:        s_downloadoptions_menu.nitems = 0;
                   3194: 
                   3195:        s_download_title.generic.type = MTYPE_SEPARATOR;
                   3196:        s_download_title.generic.name = "Download Options";
                   3197:        s_download_title.generic.x    = 48;
                   3198:        s_download_title.generic.y       = y;
                   3199: 
                   3200:        s_allow_download_box.generic.type = MTYPE_SPINCONTROL;
                   3201:        s_allow_download_box.generic.x  = 0;
                   3202:        s_allow_download_box.generic.y  = y += 20;
                   3203:        s_allow_download_box.generic.name       = "allow downloading";
                   3204:        s_allow_download_box.generic.callback = DownloadCallback;
                   3205:        s_allow_download_box.itemnames = yes_no_names;
                   3206:        s_allow_download_box.curvalue = (Cvar_VariableValue("allow_download") != 0);
                   3207: 
                   3208:        s_allow_download_maps_box.generic.type = MTYPE_SPINCONTROL;
                   3209:        s_allow_download_maps_box.generic.x     = 0;
                   3210:        s_allow_download_maps_box.generic.y     = y += 20;
                   3211:        s_allow_download_maps_box.generic.name  = "maps";
                   3212:        s_allow_download_maps_box.generic.callback = DownloadCallback;
                   3213:        s_allow_download_maps_box.itemnames = yes_no_names;
                   3214:        s_allow_download_maps_box.curvalue = (Cvar_VariableValue("allow_download_maps") != 0);
                   3215: 
                   3216:        s_allow_download_players_box.generic.type = MTYPE_SPINCONTROL;
                   3217:        s_allow_download_players_box.generic.x  = 0;
                   3218:        s_allow_download_players_box.generic.y  = y += 10;
                   3219:        s_allow_download_players_box.generic.name       = "player models/skins";
                   3220:        s_allow_download_players_box.generic.callback = DownloadCallback;
                   3221:        s_allow_download_players_box.itemnames = yes_no_names;
                   3222:        s_allow_download_players_box.curvalue = (Cvar_VariableValue("allow_download_players") != 0);
                   3223: 
                   3224:        s_allow_download_models_box.generic.type = MTYPE_SPINCONTROL;
                   3225:        s_allow_download_models_box.generic.x   = 0;
                   3226:        s_allow_download_models_box.generic.y   = y += 10;
                   3227:        s_allow_download_models_box.generic.name        = "models";
                   3228:        s_allow_download_models_box.generic.callback = DownloadCallback;
                   3229:        s_allow_download_models_box.itemnames = yes_no_names;
                   3230:        s_allow_download_models_box.curvalue = (Cvar_VariableValue("allow_download_models") != 0);
                   3231: 
                   3232:        s_allow_download_sounds_box.generic.type = MTYPE_SPINCONTROL;
                   3233:        s_allow_download_sounds_box.generic.x   = 0;
                   3234:        s_allow_download_sounds_box.generic.y   = y += 10;
                   3235:        s_allow_download_sounds_box.generic.name        = "sounds";
                   3236:        s_allow_download_sounds_box.generic.callback = DownloadCallback;
                   3237:        s_allow_download_sounds_box.itemnames = yes_no_names;
                   3238:        s_allow_download_sounds_box.curvalue = (Cvar_VariableValue("allow_download_sounds") != 0);
                   3239: 
                   3240:        Menu_AddItem( &s_downloadoptions_menu, &s_download_title );
                   3241:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_box );
                   3242:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_maps_box );
                   3243:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_players_box );
                   3244:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_models_box );
                   3245:        Menu_AddItem( &s_downloadoptions_menu, &s_allow_download_sounds_box );
                   3246: 
                   3247:        Menu_Center( &s_downloadoptions_menu );
                   3248: 
                   3249:        // skip over title
                   3250:        if (s_downloadoptions_menu.cursor == 0)
                   3251:                s_downloadoptions_menu.cursor = 1;
                   3252: }
                   3253: 
                   3254: void DownloadOptions_MenuDraw(void)
                   3255: {
                   3256:        Menu_Draw( &s_downloadoptions_menu );
                   3257: }
                   3258: 
                   3259: const char *DownloadOptions_MenuKey( int key )
                   3260: {
                   3261:        return Default_MenuKey( &s_downloadoptions_menu, key );
                   3262: }
                   3263: 
                   3264: void M_Menu_DownloadOptions_f (void)
                   3265: {
                   3266:        DownloadOptions_MenuInit();
                   3267:        M_PushMenu( DownloadOptions_MenuDraw, DownloadOptions_MenuKey );
                   3268: }
                   3269: /*
                   3270: =============================================================================
                   3271: 
1.1       root     3272: ADDRESS BOOK MENU
1.1.1.2   root     3273: 
1.1       root     3274: =============================================================================
                   3275: */
                   3276: #define NUM_ADDRESSBOOK_ENTRIES 9
1.1.1.2   root     3277: 
1.1       root     3278: static menuframework_s s_addressbook_menu;
                   3279: static menufield_s             s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES];
1.1.1.2   root     3280: 
1.1       root     3281: void AddressBook_MenuInit( void )
                   3282: {
                   3283:        int i;
1.1.1.2   root     3284: 
1.1       root     3285:        s_addressbook_menu.x = viddef.width / 2 - 142;
                   3286:        s_addressbook_menu.y = viddef.height / 2 - 58;
                   3287:        s_addressbook_menu.nitems = 0;
1.1.1.2   root     3288: 
1.1       root     3289:        for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ )
                   3290:        {
                   3291:                cvar_t *adr;
                   3292:                char buffer[20];
                   3293: 
                   3294:                Com_sprintf( buffer, sizeof( buffer ), "adr%d", i );
                   3295: 
                   3296:                adr = Cvar_Get( buffer, "", CVAR_ARCHIVE );
1.1.1.2   root     3297: 
1.1       root     3298:                s_addressbook_fields[i].generic.type = MTYPE_FIELD;
                   3299:                s_addressbook_fields[i].generic.name = 0;
                   3300:                s_addressbook_fields[i].generic.callback = 0;
                   3301:                s_addressbook_fields[i].generic.x               = 0;
                   3302:                s_addressbook_fields[i].generic.y               = i * 18 + 0;
                   3303:                s_addressbook_fields[i].generic.localdata[0] = i;
                   3304:                s_addressbook_fields[i].cursor                  = 0;
                   3305:                s_addressbook_fields[i].length                  = 60;
                   3306:                s_addressbook_fields[i].visible_length  = 30;
                   3307: 
                   3308:                strcpy( s_addressbook_fields[i].buffer, adr->string );
1.1.1.2   root     3309: 
1.1       root     3310:                Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] );
                   3311:        }
                   3312: }
1.1.1.2   root     3313: 
1.1       root     3314: const char *AddressBook_MenuKey( int key )
                   3315: {
                   3316:        if ( key == K_ESCAPE )
                   3317:        {
                   3318:                int index;
                   3319:                char buffer[20];
                   3320: 
                   3321:                for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ )
                   3322:                {
                   3323:                        Com_sprintf( buffer, sizeof( buffer ), "adr%d", index );
                   3324:                        Cvar_Set( buffer, s_addressbook_fields[index].buffer );
                   3325:                }
                   3326:        }
                   3327:        return Default_MenuKey( &s_addressbook_menu, key );
                   3328: }
1.1.1.2   root     3329: 
1.1       root     3330: void AddressBook_MenuDraw(void)
                   3331: {
                   3332:        M_Banner( "m_banner_addressbook" );
                   3333:        Menu_Draw( &s_addressbook_menu );
                   3334: }
1.1.1.2   root     3335: 
1.1       root     3336: void M_Menu_AddressBook_f(void)
                   3337: {
                   3338:        AddressBook_MenuInit();
                   3339:        M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey );
                   3340: }
1.1.1.2   root     3341: 
1.1       root     3342: /*
                   3343: =============================================================================
1.1.1.2   root     3344: 
1.1       root     3345: PLAYER CONFIG MENU
1.1.1.2   root     3346: 
1.1       root     3347: =============================================================================
                   3348: */
                   3349: static menuframework_s s_player_config_menu;
                   3350: static menufield_s             s_player_name_field;
                   3351: static menulist_s              s_player_model_box;
                   3352: static menulist_s              s_player_skin_box;
                   3353: static menulist_s              s_player_handedness_box;
1.1.1.2   root     3354: static menulist_s              s_player_rate_box;
1.1       root     3355: static menuseparator_s s_player_skin_title;
                   3356: static menuseparator_s s_player_model_title;
                   3357: static menuseparator_s s_player_hand_title;
1.1.1.2   root     3358: static menuseparator_s s_player_rate_title;
                   3359: static menuaction_s            s_player_download_action;
1.1       root     3360: 
                   3361: #define MAX_DISPLAYNAME 16
                   3362: #define MAX_PLAYERMODELS 1024
                   3363: 
                   3364: typedef struct
                   3365: {
                   3366:        int             nskins;
                   3367:        char    **skindisplaynames;
                   3368:        char    displayname[MAX_DISPLAYNAME];
                   3369:        char    directory[MAX_QPATH];
                   3370: } playermodelinfo_s;
                   3371: 
                   3372: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS];
                   3373: static char *s_pmnames[MAX_PLAYERMODELS];
                   3374: static int s_numplayermodels;
                   3375: 
1.1.1.2   root     3376: static int rate_tbl[] = { 2500, 3200, 5000, 10000, 25000, 0 };
                   3377: static const char *rate_names[] = { "28.8 Modem", "33.6 Modem", "Single ISDN",
                   3378:        "Dual ISDN/Cable", "T1/LAN", "User defined", 0 };
                   3379: 
                   3380: void DownloadOptionsFunc( void *self )
                   3381: {
                   3382:        M_Menu_DownloadOptions_f();
                   3383: }
                   3384: 
1.1       root     3385: static void HandednessCallback( void *unused )
                   3386: {
                   3387:        Cvar_SetValue( "hand", s_player_handedness_box.curvalue );
                   3388: }
                   3389: 
1.1.1.2   root     3390: static void RateCallback( void *unused )
                   3391: {
                   3392:        if (s_player_rate_box.curvalue != sizeof(rate_tbl) / sizeof(*rate_tbl) - 1)
                   3393:                Cvar_SetValue( "rate", rate_tbl[s_player_rate_box.curvalue] );
                   3394: }
                   3395: 
1.1       root     3396: static void ModelCallback( void *unused )
                   3397: {
                   3398:        s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
                   3399:        s_player_skin_box.curvalue = 0;
                   3400: }
                   3401: 
                   3402: static void FreeFileList( char **list, int n )
                   3403: {
                   3404:        int i;
                   3405: 
                   3406:        for ( i = 0; i < n; i++ )
                   3407:        {
                   3408:                if ( list[i] )
                   3409:                {
                   3410:                        free( list[i] );
                   3411:                        list[i] = 0;
                   3412:                }
                   3413:        }
                   3414:        free( list );
                   3415: }
                   3416: 
                   3417: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles )
                   3418: {
                   3419:        int i;
                   3420:        char scratch[1024];
                   3421: 
                   3422:        strcpy( scratch, skin );
                   3423:        *strrchr( scratch, '.' ) = 0;
                   3424:        strcat( scratch, "_i.pcx" );
                   3425: 
                   3426:        for ( i = 0; i < npcxfiles; i++ )
                   3427:        {
                   3428:                if ( strcmp( pcxfiles[i], scratch ) == 0 )
                   3429:                        return true;
                   3430:        }
                   3431: 
                   3432:        return false;
                   3433: }
                   3434: 
                   3435: static qboolean PlayerConfig_ScanDirectories( void )
                   3436: {
                   3437:        char findname[1024];
                   3438:        char scratch[1024];
                   3439:        int ndirs = 0, npms = 0;
                   3440:        char **dirnames;
                   3441:        char *path = NULL;
                   3442:        int i;
                   3443: 
                   3444:        extern char **FS_ListFiles( char *, int *, unsigned, unsigned );
                   3445: 
                   3446:        s_numplayermodels = 0;
                   3447: 
                   3448:        /*
                   3449:        ** get a list of directories
                   3450:        */
                   3451:        do 
                   3452:        {
                   3453:                path = FS_NextPath( path );
                   3454:                Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path );
                   3455: 
                   3456:                if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 )
                   3457:                        break;
                   3458:        } while ( path );
                   3459: 
                   3460:        if ( !dirnames )
                   3461:                return false;
                   3462: 
                   3463:        /*
                   3464:        ** go through the subdirectories
                   3465:        */
                   3466:        npms = ndirs;
                   3467:        if ( npms > MAX_PLAYERMODELS )
                   3468:                npms = MAX_PLAYERMODELS;
                   3469: 
                   3470:        for ( i = 0; i < npms; i++ )
                   3471:        {
                   3472:                int k, s;
                   3473:                char *a, *b, *c;
                   3474:                char **pcxnames;
                   3475:                char **skinnames;
                   3476:                int npcxfiles;
                   3477:                int nskins = 0;
                   3478: 
                   3479:                if ( dirnames[i] == 0 )
                   3480:                        continue;
                   3481: 
                   3482:                // verify the existence of tris.md2
                   3483:                strcpy( scratch, dirnames[i] );
                   3484:                strcat( scratch, "/tris.md2" );
                   3485:                if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) )
                   3486:                {
                   3487:                        free( dirnames[i] );
                   3488:                        dirnames[i] = 0;
                   3489:                        Sys_FindClose();
                   3490:                        continue;
                   3491:                }
                   3492:                Sys_FindClose();
                   3493: 
                   3494:                // verify the existence of at least one pcx skin
                   3495:                strcpy( scratch, dirnames[i] );
                   3496:                strcat( scratch, "/*.pcx" );
                   3497:                pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM );
                   3498: 
                   3499:                if ( !pcxnames )
                   3500:                {
                   3501:                        free( dirnames[i] );
                   3502:                        dirnames[i] = 0;
                   3503:                        continue;
                   3504:                }
                   3505: 
                   3506:                // count valid skins, which consist of a skin with a matching "_i" icon
                   3507:                for ( k = 0; k < npcxfiles-1; k++ )
                   3508:                {
                   3509:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
                   3510:                        {
                   3511:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
                   3512:                                {
                   3513:                                        nskins++;
                   3514:                                }
                   3515:                        }
                   3516:                }
                   3517:                if ( !nskins )
                   3518:                        continue;
                   3519: 
                   3520:                skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) );
                   3521:                memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) );
                   3522: 
                   3523:                // copy the valid skins
                   3524:                for ( s = 0, k = 0; k < npcxfiles-1; k++ )
                   3525:                {
                   3526:                        char *a, *b, *c;
                   3527: 
                   3528:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
                   3529:                        {
                   3530:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
                   3531:                                {
                   3532:                                        a = strrchr( pcxnames[k], '/' );
                   3533:                                        b = strrchr( pcxnames[k], '\\' );
                   3534: 
                   3535:                                        if ( a > b )
                   3536:                                                c = a;
                   3537:                                        else
                   3538:                                                c = b;
                   3539: 
                   3540:                                        strcpy( scratch, c + 1 );
                   3541: 
                   3542:                                        if ( strrchr( scratch, '.' ) )
                   3543:                                                *strrchr( scratch, '.' ) = 0;
                   3544: 
                   3545:                                        skinnames[s] = strdup( scratch );
                   3546:                                        s++;
                   3547:                                }
                   3548:                        }
                   3549:                }
                   3550: 
                   3551:                // at this point we have a valid player model
                   3552:                s_pmi[s_numplayermodels].nskins = nskins;
                   3553:                s_pmi[s_numplayermodels].skindisplaynames = skinnames;
                   3554: 
                   3555:                // make short name for the model
                   3556:                a = strrchr( dirnames[i], '/' );
                   3557:                b = strrchr( dirnames[i], '\\' );
                   3558: 
                   3559:                if ( a > b )
                   3560:                        c = a;
                   3561:                else
                   3562:                        c = b;
                   3563: 
                   3564:                strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 );
                   3565:                strcpy( s_pmi[s_numplayermodels].directory, c + 1 );
                   3566: 
                   3567:                FreeFileList( pcxnames, npcxfiles );
                   3568: 
                   3569:                s_numplayermodels++;
                   3570:        }
                   3571:        if ( dirnames )
                   3572:                FreeFileList( dirnames, ndirs );
                   3573: }
                   3574: 
                   3575: static int pmicmpfnc( const void *_a, const void *_b )
                   3576: {
                   3577:        const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a;
                   3578:        const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b;
                   3579: 
                   3580:        /*
                   3581:        ** sort by male, female, then alphabetical
                   3582:        */
                   3583:        if ( strcmp( a->directory, "male" ) == 0 )
                   3584:                return -1;
                   3585:        else if ( strcmp( b->directory, "male" ) == 0 )
                   3586:                return 1;
                   3587: 
                   3588:        if ( strcmp( a->directory, "female" ) == 0 )
                   3589:                return -1;
                   3590:        else if ( strcmp( b->directory, "female" ) == 0 )
                   3591:                return 1;
                   3592: 
                   3593:        return strcmp( a->directory, b->directory );
                   3594: }
                   3595: 
1.1.1.2   root     3596: 
                   3597: qboolean PlayerConfig_MenuInit( void )
1.1       root     3598: {
                   3599:        extern cvar_t *name;
                   3600:        extern cvar_t *team;
                   3601:        extern cvar_t *skin;
                   3602:        char currentdirectory[1024];
                   3603:        char currentskin[1024];
                   3604:        int i = 0;
                   3605: 
                   3606:        int currentdirectoryindex = 0;
                   3607:        int currentskinindex = 0;
                   3608: 
                   3609:        cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
                   3610: 
                   3611:        static const char *handedness[] = { "right", "left", "center", 0 };
                   3612: 
                   3613:        PlayerConfig_ScanDirectories();
                   3614: 
1.1.1.2   root     3615:        if (s_numplayermodels == 0)
                   3616:                return false;
                   3617: 
1.1       root     3618:        if ( hand->value < 0 || hand->value > 2 )
                   3619:                Cvar_SetValue( "hand", 0 );
                   3620: 
                   3621:        strcpy( currentdirectory, skin->string );
                   3622: 
                   3623:        if ( strchr( currentdirectory, '/' ) )
                   3624:        {
                   3625:                strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 );
                   3626:                *strchr( currentdirectory, '/' ) = 0;
                   3627:        }
                   3628:        else if ( strchr( currentdirectory, '\\' ) )
                   3629:        {
                   3630:                strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 );
                   3631:                *strchr( currentdirectory, '\\' ) = 0;
                   3632:        }
                   3633:        else
                   3634:        {
                   3635:                strcpy( currentdirectory, "male" );
                   3636:                strcpy( currentskin, "grunt" );
                   3637:        }
                   3638: 
                   3639:        qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc );
                   3640: 
                   3641:        memset( s_pmnames, 0, sizeof( s_pmnames ) );
                   3642:        for ( i = 0; i < s_numplayermodels; i++ )
                   3643:        {
                   3644:                s_pmnames[i] = s_pmi[i].displayname;
                   3645:                if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 )
                   3646:                {
                   3647:                        int j;
                   3648: 
                   3649:                        currentdirectoryindex = i;
                   3650: 
                   3651:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
                   3652:                        {
                   3653:                                if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 )
                   3654:                                {
                   3655:                                        currentskinindex = j;
                   3656:                                        break;
                   3657:                                }
                   3658:                        }
                   3659:                }
                   3660:        }
                   3661: 
                   3662:        s_player_config_menu.x = viddef.width / 2 - 95; 
                   3663:        s_player_config_menu.y = viddef.height / 2 - 97;
                   3664:        s_player_config_menu.nitems = 0;
                   3665: 
                   3666:        s_player_name_field.generic.type = MTYPE_FIELD;
                   3667:        s_player_name_field.generic.name = "name";
                   3668:        s_player_name_field.generic.callback = 0;
                   3669:        s_player_name_field.generic.x           = 0;
                   3670:        s_player_name_field.generic.y           = 0;
                   3671:        s_player_name_field.length      = 20;
                   3672:        s_player_name_field.visible_length = 20;
                   3673:        strcpy( s_player_name_field.buffer, name->string );
                   3674:        s_player_name_field.cursor = strlen( name->string );
                   3675: 
                   3676:        s_player_model_title.generic.type = MTYPE_SEPARATOR;
                   3677:        s_player_model_title.generic.name = "model";
                   3678:        s_player_model_title.generic.x    = -8;
                   3679:        s_player_model_title.generic.y   = 60;
                   3680: 
                   3681:        s_player_model_box.generic.type = MTYPE_SPINCONTROL;
                   3682:        s_player_model_box.generic.x    = -56;
                   3683:        s_player_model_box.generic.y    = 70;
                   3684:        s_player_model_box.generic.callback = ModelCallback;
                   3685:        s_player_model_box.generic.cursor_offset = -48;
                   3686:        s_player_model_box.curvalue = currentdirectoryindex;
                   3687:        s_player_model_box.itemnames = s_pmnames;
                   3688: 
                   3689:        s_player_skin_title.generic.type = MTYPE_SEPARATOR;
                   3690:        s_player_skin_title.generic.name = "skin";
                   3691:        s_player_skin_title.generic.x    = -16;
                   3692:        s_player_skin_title.generic.y    = 84;
                   3693: 
                   3694:        s_player_skin_box.generic.type = MTYPE_SPINCONTROL;
                   3695:        s_player_skin_box.generic.x     = -56;
                   3696:        s_player_skin_box.generic.y     = 94;
                   3697:        s_player_skin_box.generic.name  = 0;
                   3698:        s_player_skin_box.generic.callback = 0;
                   3699:        s_player_skin_box.generic.cursor_offset = -48;
                   3700:        s_player_skin_box.curvalue = currentskinindex;
                   3701:        s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
                   3702: 
                   3703:        s_player_hand_title.generic.type = MTYPE_SEPARATOR;
                   3704:        s_player_hand_title.generic.name = "handedness";
                   3705:        s_player_hand_title.generic.x    = 32;
                   3706:        s_player_hand_title.generic.y    = 108;
                   3707: 
                   3708:        s_player_handedness_box.generic.type = MTYPE_SPINCONTROL;
                   3709:        s_player_handedness_box.generic.x       = -56;
                   3710:        s_player_handedness_box.generic.y       = 118;
                   3711:        s_player_handedness_box.generic.name    = 0;
                   3712:        s_player_handedness_box.generic.cursor_offset = -48;
                   3713:        s_player_handedness_box.generic.callback = HandednessCallback;
                   3714:        s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" );
                   3715:        s_player_handedness_box.itemnames = handedness;
                   3716: 
1.1.1.2   root     3717:        for (i = 0; i < sizeof(rate_tbl) / sizeof(*rate_tbl) - 1; i++)
                   3718:                if (Cvar_VariableValue("rate") == rate_tbl[i])
                   3719:                        break;
                   3720: 
                   3721:        s_player_rate_title.generic.type = MTYPE_SEPARATOR;
                   3722:        s_player_rate_title.generic.name = "connect speed";
                   3723:        s_player_rate_title.generic.x    = 56;
                   3724:        s_player_rate_title.generic.y    = 156;
                   3725: 
                   3726:        s_player_rate_box.generic.type = MTYPE_SPINCONTROL;
                   3727:        s_player_rate_box.generic.x     = -56;
                   3728:        s_player_rate_box.generic.y     = 166;
                   3729:        s_player_rate_box.generic.name  = 0;
                   3730:        s_player_rate_box.generic.cursor_offset = -48;
                   3731:        s_player_rate_box.generic.callback = RateCallback;
                   3732:        s_player_rate_box.curvalue = i;
                   3733:        s_player_rate_box.itemnames = rate_names;
                   3734: 
                   3735:        s_player_download_action.generic.type = MTYPE_ACTION;
                   3736:        s_player_download_action.generic.name   = "download options";
                   3737:        s_player_download_action.generic.flags= QMF_LEFT_JUSTIFY;
                   3738:        s_player_download_action.generic.x      = -24;
                   3739:        s_player_download_action.generic.y      = 186;
                   3740:        s_player_download_action.generic.statusbar = NULL;
                   3741:        s_player_download_action.generic.callback = DownloadOptionsFunc;
                   3742: 
1.1       root     3743:        Menu_AddItem( &s_player_config_menu, &s_player_name_field );
                   3744:        Menu_AddItem( &s_player_config_menu, &s_player_model_title );
                   3745:        Menu_AddItem( &s_player_config_menu, &s_player_model_box );
                   3746:        if ( s_player_skin_box.itemnames )
                   3747:        {
                   3748:                Menu_AddItem( &s_player_config_menu, &s_player_skin_title );
                   3749:                Menu_AddItem( &s_player_config_menu, &s_player_skin_box );
                   3750:        }
                   3751:        Menu_AddItem( &s_player_config_menu, &s_player_hand_title );
                   3752:        Menu_AddItem( &s_player_config_menu, &s_player_handedness_box );
1.1.1.2   root     3753:        Menu_AddItem( &s_player_config_menu, &s_player_rate_title );
                   3754:        Menu_AddItem( &s_player_config_menu, &s_player_rate_box );
                   3755:        Menu_AddItem( &s_player_config_menu, &s_player_download_action );
                   3756: 
                   3757:        return true;
1.1       root     3758: }
                   3759: 
                   3760: void PlayerConfig_MenuDraw( void )
                   3761: {
                   3762:        extern float CalcFov( float fov_x, float w, float h );
                   3763:        refdef_t refdef;
                   3764:        char scratch[MAX_QPATH];
                   3765: 
                   3766:        memset( &refdef, 0, sizeof( refdef ) );
                   3767: 
                   3768:        refdef.x = viddef.width / 2;
                   3769:        refdef.y = viddef.height / 2 - 72;
                   3770:        refdef.width = 144;
                   3771:        refdef.height = 168;
                   3772:        refdef.fov_x = 40;
                   3773:        refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height );
                   3774:        refdef.time = cls.realtime*0.001;
                   3775: 
                   3776:        if ( s_pmi[s_player_model_box.curvalue].skindisplaynames )
                   3777:        {
                   3778:                static int yaw;
                   3779:                int maxframe = 29;
                   3780:                entity_t entity;
                   3781: 
                   3782:                memset( &entity, 0, sizeof( entity ) );
                   3783: 
                   3784:                Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory );
                   3785:                entity.model = re.RegisterModel( scratch );
                   3786:                Com_sprintf( scratch, sizeof( scratch ), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
                   3787:                entity.skin = re.RegisterSkin( scratch );
                   3788:                entity.flags = RF_FULLBRIGHT;
                   3789:                entity.origin[0] = 80;
                   3790:                entity.origin[1] = 0;
                   3791:                entity.origin[2] = 0;
                   3792:                VectorCopy( entity.origin, entity.oldorigin );
                   3793:                entity.frame = 0;
                   3794:                entity.oldframe = 0;
                   3795:                entity.backlerp = 0.0;
                   3796:                entity.angles[1] = yaw++;
                   3797:                if ( ++yaw > 360 )
                   3798:                        yaw -= 360;
                   3799: 
                   3800:                refdef.areabits = 0;
                   3801:                refdef.num_entities = 1;
                   3802:                refdef.entities = &entity;
                   3803:                refdef.lightstyles = 0;
                   3804:                refdef.rdflags = RDF_NOWORLDMODEL;
                   3805: 
                   3806:                Menu_Draw( &s_player_config_menu );
                   3807: 
                   3808:                M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 );
                   3809:                refdef.height += 4;
                   3810: 
                   3811:                re.RenderFrame( &refdef );
                   3812: 
                   3813:                Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx", 
                   3814:                        s_pmi[s_player_model_box.curvalue].directory,
                   3815:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
                   3816:                re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch );
                   3817:        }
                   3818: }
1.1.1.2   root     3819: 
1.1       root     3820: const char *PlayerConfig_MenuKey (int key)
                   3821: {
                   3822:        int i;
                   3823: 
                   3824:        if ( key == K_ESCAPE )
                   3825:        {
                   3826:                char scratch[1024];
                   3827: 
                   3828:                Cvar_Set( "name", s_player_name_field.buffer );
                   3829: 
                   3830:                Com_sprintf( scratch, sizeof( scratch ), "%s/%s", 
                   3831:                        s_pmi[s_player_model_box.curvalue].directory, 
1.1.1.3   root     3832:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
1.1       root     3833: 
                   3834:                Cvar_Set( "skin", scratch );
                   3835: 
                   3836:                for ( i = 0; i < s_numplayermodels; i++ )
                   3837:                {
                   3838:                        int j;
                   3839: 
                   3840:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
                   3841:                        {
                   3842:                                if ( s_pmi[i].skindisplaynames[j] )
                   3843:                                        free( s_pmi[i].skindisplaynames[j] );
                   3844:                                s_pmi[i].skindisplaynames[j] = 0;
                   3845:                        }
                   3846:                        free( s_pmi[i].skindisplaynames );
                   3847:                        s_pmi[i].skindisplaynames = 0;
                   3848:                        s_pmi[i].nskins = 0;
                   3849:                }
                   3850:        }
                   3851:        return Default_MenuKey( &s_player_config_menu, key );
                   3852: }
1.1.1.2   root     3853: 
                   3854: 
1.1       root     3855: void M_Menu_PlayerConfig_f (void)
                   3856: {
1.1.1.2   root     3857:        if (!PlayerConfig_MenuInit())
                   3858:        {
                   3859:                Menu_SetStatusBar( &s_multiplayer_menu, "No valid player models found" );
                   3860:                return;
                   3861:        }
                   3862:        Menu_SetStatusBar( &s_multiplayer_menu, NULL );
1.1       root     3863:        M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey );
                   3864: }
1.1.1.2   root     3865: 
                   3866: 
1.1       root     3867: /*
                   3868: =======================================================================
                   3869: 
                   3870: GALLERY MENU
                   3871: 
                   3872: =======================================================================
                   3873: */
                   3874: #if 0
                   3875: void M_Menu_Gallery_f( void )
                   3876: {
                   3877:        extern void Gallery_MenuDraw( void );
                   3878:        extern const char *Gallery_MenuKey( int key );
1.1.1.2   root     3879: 
1.1       root     3880:        M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey );
                   3881: }
                   3882: #endif
1.1.1.2   root     3883: 
1.1       root     3884: /*
                   3885: =======================================================================
1.1.1.2   root     3886: 
1.1       root     3887: QUIT MENU
1.1.1.2   root     3888: 
1.1       root     3889: =======================================================================
                   3890: */
1.1.1.2   root     3891: 
1.1       root     3892: const char *M_Quit_Key (int key)
                   3893: {
                   3894:        switch (key)
                   3895:        {
                   3896:        case K_ESCAPE:
                   3897:        case 'n':
                   3898:        case 'N':
                   3899:                M_PopMenu ();
                   3900:                break;
1.1.1.2   root     3901: 
1.1       root     3902:        case 'Y':
                   3903:        case 'y':
                   3904:                cls.key_dest = key_console;
                   3905:                CL_Quit_f ();
                   3906:                break;
1.1.1.2   root     3907: 
1.1       root     3908:        default:
                   3909:                break;
                   3910:        }
1.1.1.2   root     3911: 
1.1       root     3912:        return NULL;
1.1.1.2   root     3913: 
1.1       root     3914: }
1.1.1.2   root     3915: 
                   3916: 
1.1       root     3917: void M_Quit_Draw (void)
                   3918: {
                   3919:        int             w, h;
1.1.1.2   root     3920: 
1.1       root     3921:        re.DrawGetPicSize (&w, &h, "quit");
                   3922:        re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit");
                   3923: }
1.1.1.2   root     3924: 
                   3925: 
1.1       root     3926: void M_Menu_Quit_f (void)
                   3927: {
                   3928:        M_PushMenu (M_Quit_Draw, M_Quit_Key);
                   3929: }
1.1.1.2   root     3930: 
                   3931: 
                   3932: 
1.1       root     3933: //=============================================================================
                   3934: /* Menu Subsystem */
1.1.1.2   root     3935: 
                   3936: 
1.1       root     3937: /*
                   3938: =================
                   3939: M_Init
                   3940: =================
                   3941: */
                   3942: void M_Init (void)
                   3943: {
                   3944:        Cmd_AddCommand ("menu_main", M_Menu_Main_f);
                   3945:        Cmd_AddCommand ("menu_game", M_Menu_Game_f);
                   3946:                Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f);
                   3947:                Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f);
                   3948:                Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f);
                   3949:                        Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f);
                   3950:                Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f);
                   3951:                        Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f);
                   3952:                Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f);
1.1.1.2   root     3953:                        Cmd_AddCommand ("menu_downloadoptions", M_Menu_DownloadOptions_f);
1.1       root     3954:                Cmd_AddCommand ("menu_credits", M_Menu_Credits_f );
                   3955:        Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f );
                   3956:        Cmd_AddCommand ("menu_video", M_Menu_Video_f);
                   3957:        Cmd_AddCommand ("menu_options", M_Menu_Options_f);
                   3958:                Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
                   3959:        Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
                   3960: }
1.1.1.2   root     3961: 
                   3962: 
1.1       root     3963: /*
                   3964: =================
                   3965: M_Draw
                   3966: =================
                   3967: */
                   3968: void M_Draw (void)
                   3969: {
                   3970:        if (cls.key_dest != key_menu)
                   3971:                return;
1.1.1.2   root     3972: 
1.1       root     3973:        // repaint everything next frame
                   3974:        SCR_DirtyScreen ();
1.1.1.2   root     3975: 
1.1       root     3976:        // dim everything behind it down
                   3977:        if (cl.cinematictime > 0)
                   3978:                re.DrawFill (0,0,viddef.width, viddef.height, 0);
                   3979:        else
                   3980:                re.DrawFadeScreen ();
1.1.1.2   root     3981: 
1.1       root     3982:        m_drawfunc ();
1.1.1.2   root     3983: 
1.1       root     3984:        // delay playing the enter sound until after the
                   3985:        // menu has been drawn, to avoid delay while
                   3986:        // caching images
                   3987:        if (m_entersound)
                   3988:        {
                   3989:                S_StartLocalSound( menu_in_sound );
                   3990:                m_entersound = false;
                   3991:        }
                   3992: }
1.1.1.2   root     3993: 
                   3994: 
1.1       root     3995: /*
                   3996: =================
                   3997: M_Keydown
                   3998: =================
                   3999: */
                   4000: void M_Keydown (int key)
                   4001: {
                   4002:        const char *s;
1.1.1.2   root     4003: 
1.1       root     4004:        if (m_keyfunc)
                   4005:                if ( ( s = m_keyfunc( key ) ) != 0 )
                   4006:                        S_StartLocalSound( ( char * ) s );
                   4007: }
1.1.1.2   root     4008: 
                   4009: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.