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

1.1     ! root        1: #include <ctype.h>
        !             2: #include <io.h>
        !             3: #include "client.h"
        !             4: #include "../client/qmenu.h"
        !             5: static int     m_main_cursor;
        !             6: #define NUM_CURSOR_FRAMES 15
        !             7: static char *menu_in_sound             = "misc/menu1.wav";
        !             8: static char *menu_move_sound   = "misc/menu2.wav";
        !             9: static char *menu_out_sound            = "misc/menu3.wav";
        !            10: void M_Menu_Main_f (void);
        !            11:        void M_Menu_Game_f (void);
        !            12:                void M_Menu_LoadGame_f (void);
        !            13:                void M_Menu_SaveGame_f (void);
        !            14:                void M_Menu_PlayerConfig_f (void);
        !            15:                void M_Menu_Credits_f( void );
        !            16:        void M_Menu_Multiplayer_f( void );
        !            17:                void M_Menu_JoinServer_f (void);
        !            18:                        void M_Menu_AddressBook_f( void );
        !            19:                void M_Menu_StartServer_f (void);
        !            20:                        void M_Menu_DMOptions_f (void);
        !            21:        void M_Menu_Video_f (void);
        !            22:        void M_Menu_Options_f (void);
        !            23:                void M_Menu_Keys_f (void);
        !            24:        void M_Menu_Quit_f (void);
        !            25: 
        !            26:        void M_Menu_Credits( void );
        !            27: qboolean       m_entersound;           // play after drawing a frame, so caching
        !            28:                                                                // won't disrupt the sound
        !            29: void   (*m_drawfunc) (void);
        !            30: const char *(*m_keyfunc) (int key);
        !            31: //=============================================================================
        !            32: /* Support Routines */
        !            33: #define        MAX_MENU_DEPTH  8
        !            34: typedef struct
        !            35: {
        !            36:        void    (*draw) (void);
        !            37:        const char *(*key) (int k);
        !            38: } menulayer_t;
        !            39: menulayer_t    m_layers[MAX_MENU_DEPTH];
        !            40: int            m_menudepth;
        !            41: 
        !            42: static void M_Banner( char *name )
        !            43: {
        !            44:        int w, h;
        !            45: 
        !            46:        re.DrawGetPicSize (&w, &h, name );
        !            47:        re.DrawPic( viddef.width / 2 - w / 2, viddef.height / 2 - 110, name );
        !            48: }
        !            49: void M_PushMenu ( void (*draw) (void), const char *(*key) (int k) )
        !            50: {
        !            51:        int             i;
        !            52: 
        !            53:        if (Cvar_VariableValue ("maxclients") == 1 
        !            54:                && Com_ServerState ())
        !            55:                Cvar_Set ("paused", "1");
        !            56:        // if this menu is already present, drop back to that level
        !            57:        // to avoid stacking menus by hotkeys
        !            58:        for (i=0 ; i<m_menudepth ; i++)
        !            59:                if (m_layers[i].draw == draw &&
        !            60:                        m_layers[i].key == key)
        !            61:                {
        !            62:                        m_menudepth = i;
        !            63:                }
        !            64:        if (i == m_menudepth)
        !            65:        {
        !            66:                if (m_menudepth >= MAX_MENU_DEPTH)
        !            67:                        Com_Error (ERR_FATAL, "M_PushMenu: MAX_MENU_DEPTH");
        !            68:                m_layers[m_menudepth].draw = m_drawfunc;
        !            69:                m_layers[m_menudepth].key = m_keyfunc;
        !            70:                m_menudepth++;
        !            71:        }
        !            72:        m_drawfunc = draw;
        !            73:        m_keyfunc = key;
        !            74:        m_entersound = true;
        !            75:        cls.key_dest = key_menu;
        !            76: }
        !            77: void M_ForceMenuOff (void)
        !            78: {
        !            79:        m_drawfunc = 0;
        !            80:        m_keyfunc = 0;
        !            81:        cls.key_dest = key_game;
        !            82:        m_menudepth = 0;
        !            83:        Key_ClearStates ();
        !            84:        Cvar_Set ("paused", "0");
        !            85: }
        !            86: void M_PopMenu (void)
        !            87: {
        !            88:        S_StartLocalSound( menu_out_sound );
        !            89:        if (m_menudepth < 1)
        !            90:                Com_Error (ERR_FATAL, "M_PopMenu: depth < 1");
        !            91:        m_menudepth--;
        !            92:        m_drawfunc = m_layers[m_menudepth].draw;
        !            93:        m_keyfunc = m_layers[m_menudepth].key;
        !            94:        if (!m_menudepth)
        !            95:                M_ForceMenuOff ();
        !            96: }
        !            97: const char *Default_MenuKey( menuframework_s *m, int key )
        !            98: {
        !            99:        const char *sound = NULL;
        !           100:        menucommon_s *item;
        !           101:        if ( m )
        !           102:        {
        !           103:                if ( ( item = Menu_ItemAtCursor( m ) ) != 0 )
        !           104:                {
        !           105:                        if ( item->type == MTYPE_FIELD )
        !           106:                        {
        !           107:                                if ( Field_Key( ( menufield_s * ) item, key ) )
        !           108:                                        return NULL;
        !           109:                        }
        !           110:                }
        !           111:        }
        !           112:        switch ( key )
        !           113:        {
        !           114:        case K_ESCAPE:
        !           115:                M_PopMenu();
        !           116:                return menu_out_sound;
        !           117:        case K_KP_UPARROW:
        !           118:        case K_UPARROW:
        !           119:                if ( m )
        !           120:                {
        !           121:                        m->cursor--;
        !           122:                        Menu_AdjustCursor( m, -1 );
        !           123:                        sound = menu_move_sound;
        !           124:                }
        !           125:                break;
        !           126:        case K_TAB:
        !           127:                if ( m )
        !           128:                {
        !           129:                        m->cursor++;
        !           130:                        Menu_AdjustCursor( m, 1 );
        !           131:                        sound = menu_move_sound;
        !           132:                }
        !           133:                break;
        !           134:        case K_KP_DOWNARROW:
        !           135:        case K_DOWNARROW:
        !           136:                if ( m )
        !           137:                {
        !           138:                        m->cursor++;
        !           139:                        Menu_AdjustCursor( m, 1 );
        !           140:                        sound = menu_move_sound;
        !           141:                }
        !           142:                break;
        !           143:        case K_KP_LEFTARROW:
        !           144:        case K_LEFTARROW:
        !           145:                if ( m )
        !           146:                {
        !           147:                        Menu_SlideItem( m, -1 );
        !           148:                        sound = menu_move_sound;
        !           149:                }
        !           150:                break;
        !           151:        case K_KP_RIGHTARROW:
        !           152:        case K_RIGHTARROW:
        !           153:                if ( m )
        !           154:                {
        !           155:                        Menu_SlideItem( m, 1 );
        !           156:                        sound = menu_move_sound;
        !           157:                }
        !           158:                break;
        !           159: 
        !           160:        case K_MOUSE1:
        !           161:        case K_MOUSE2:
        !           162:        case K_MOUSE3:
        !           163:        case K_JOY1:
        !           164:        case K_JOY2:
        !           165:        case K_JOY3:
        !           166:        case K_JOY4:
        !           167:        case K_AUX1:
        !           168:        case K_AUX2:
        !           169:        case K_AUX3:
        !           170:        case K_AUX4:
        !           171:        case K_AUX5:
        !           172:        case K_AUX6:
        !           173:        case K_AUX7:
        !           174:        case K_AUX8:
        !           175:        case K_AUX9:
        !           176:        case K_AUX10:
        !           177:        case K_AUX11:
        !           178:        case K_AUX12:
        !           179:        case K_AUX13:
        !           180:        case K_AUX14:
        !           181:        case K_AUX15:
        !           182:        case K_AUX16:
        !           183:        case K_AUX17:
        !           184:        case K_AUX18:
        !           185:        case K_AUX19:
        !           186:        case K_AUX20:
        !           187:        case K_AUX21:
        !           188:        case K_AUX22:
        !           189:        case K_AUX23:
        !           190:        case K_AUX24:
        !           191:        case K_AUX25:
        !           192:        case K_AUX26:
        !           193:        case K_AUX27:
        !           194:        case K_AUX28:
        !           195:        case K_AUX29:
        !           196:        case K_AUX30:
        !           197:        case K_AUX31:
        !           198:        case K_AUX32:
        !           199:                
        !           200:        case K_KP_ENTER:
        !           201:        case K_ENTER:
        !           202:                if ( m )
        !           203:                        Menu_SelectItem( m );
        !           204:                sound = menu_move_sound;
        !           205:                break;
        !           206:        }
        !           207:        return sound;
        !           208: }
        !           209: //=============================================================================
        !           210: /*
        !           211: ================
        !           212: M_DrawCharacter
        !           213: Draws one solid graphics character
        !           214: cx and cy are in 320*240 coordinates, and will be centered on
        !           215: higher res screens.
        !           216: ================
        !           217: */
        !           218: void M_DrawCharacter (int cx, int cy, int num)
        !           219: {
        !           220:        re.DrawChar ( cx + ((viddef.width - 320)>>1), cy + ((viddef.height - 240)>>1), num);
        !           221: }
        !           222: void M_Print (int cx, int cy, char *str)
        !           223: {
        !           224:        while (*str)
        !           225:        {
        !           226:                M_DrawCharacter (cx, cy, (*str)+128);
        !           227:                str++;
        !           228:                cx += 8;
        !           229:        }
        !           230: }
        !           231: void M_PrintWhite (int cx, int cy, char *str)
        !           232: {
        !           233:        while (*str)
        !           234:        {
        !           235:                M_DrawCharacter (cx, cy, *str);
        !           236:                str++;
        !           237:                cx += 8;
        !           238:        }
        !           239: }
        !           240: void M_DrawPic (int x, int y, char *pic)
        !           241: {
        !           242:        re.DrawPic (x + ((viddef.width - 320)>>1), y + ((viddef.height - 240)>>1), pic);
        !           243: }
        !           244: /*
        !           245: =============
        !           246: M_DrawCursor
        !           247: Draws an animating cursor with the point at
        !           248: x,y.  The pic will extend to the left of x,
        !           249: and both above and below y.
        !           250: =============
        !           251: */
        !           252: void M_DrawCursor( int x, int y, int f )
        !           253: {
        !           254:        char    cursorname[80];
        !           255:        static qboolean cached;
        !           256: 
        !           257:        if ( !cached )
        !           258:        {
        !           259:                int i;
        !           260: 
        !           261:                for ( i = 0; i < NUM_CURSOR_FRAMES; i++ )
        !           262:                {
        !           263:                        Com_sprintf( cursorname, sizeof( cursorname ), "m_cursor%d", i );
        !           264: 
        !           265:                        re.RegisterPic( cursorname );
        !           266:                }
        !           267:                cached = true;
        !           268:        }
        !           269:        Com_sprintf( cursorname, sizeof(cursorname), "m_cursor%d", f );
        !           270:        re.DrawPic( x, y, cursorname );
        !           271: }
        !           272: void M_DrawTextBox (int x, int y, int width, int lines)
        !           273: {
        !           274:        int             cx, cy;
        !           275:        int             n;
        !           276:        // draw left side
        !           277:        cx = x;
        !           278:        cy = y;
        !           279:        M_DrawCharacter (cx, cy, 1);
        !           280:        for (n = 0; n < lines; n++)
        !           281:        {
        !           282:                cy += 8;
        !           283:                M_DrawCharacter (cx, cy, 4);
        !           284:        }
        !           285:        M_DrawCharacter (cx, cy+8, 7);
        !           286:        // draw middle
        !           287:        cx += 8;
        !           288:        while (width > 0)
        !           289:        {
        !           290:                cy = y;
        !           291:                M_DrawCharacter (cx, cy, 2);
        !           292:                for (n = 0; n < lines; n++)
        !           293:                {
        !           294:                        cy += 8;
        !           295:                        M_DrawCharacter (cx, cy, 5);
        !           296:                }
        !           297:                M_DrawCharacter (cx, cy+8, 8);
        !           298:                width -= 1;
        !           299:                cx += 8;
        !           300:        }
        !           301:        // draw right side
        !           302:        cy = y;
        !           303:        M_DrawCharacter (cx, cy, 3);
        !           304:        for (n = 0; n < lines; n++)
        !           305:        {
        !           306:                cy += 8;
        !           307:                M_DrawCharacter (cx, cy, 6);
        !           308:        }
        !           309:        M_DrawCharacter (cx, cy+8, 9);
        !           310: }
        !           311:                
        !           312: /*
        !           313: =======================================================================
        !           314: MAIN MENU
        !           315: =======================================================================
        !           316: */
        !           317: #define        MAIN_ITEMS      5
        !           318: void M_Main_Draw (void)
        !           319: {
        !           320:        int i;
        !           321:        int w, h;
        !           322:        int ystart;
        !           323:        int     xoffset;
        !           324:        int widest = -1;
        !           325:        int totalheight = 0;
        !           326:        char litname[80];
        !           327:        char *names[] =
        !           328:        {
        !           329:                "m_main_game",
        !           330:                "m_main_multiplayer",
        !           331:                "m_main_options",
        !           332:                "m_main_video",
        !           333:                "m_main_quit",
        !           334:                0
        !           335:        };
        !           336:        for ( i = 0; names[i] != 0; i++ )
        !           337:        {
        !           338:                re.DrawGetPicSize( &w, &h, names[i] );
        !           339:                if ( w > widest )
        !           340:                        widest = w;
        !           341:                totalheight += ( h + 12 );
        !           342:        }
        !           343: 
        !           344:        ystart = ( viddef.height / 2 - 110 );
        !           345:        xoffset = ( viddef.width - widest + 70 ) / 2;
        !           346:        for ( i = 0; names[i] != 0; i++ )
        !           347:        {
        !           348:                if ( i != m_main_cursor )
        !           349:                        re.DrawPic( xoffset, ystart + i * 40 + 13, names[i] );
        !           350:        }
        !           351:        strcpy( litname, names[m_main_cursor] );
        !           352:        strcat( litname, "_sel" );
        !           353:        re.DrawPic( xoffset, ystart + m_main_cursor * 40 + 13, litname );
        !           354:        M_DrawCursor( xoffset - 25, ystart + m_main_cursor * 40 + 11, (int)(cls.realtime / 100)%NUM_CURSOR_FRAMES );
        !           355:        re.DrawGetPicSize( &w, &h, "m_main_plaque" );
        !           356:        re.DrawPic( xoffset - 30 - w, ystart, "m_main_plaque" );
        !           357:        re.DrawPic( xoffset - 30 - w, ystart + h + 5, "m_main_logo" );
        !           358: }
        !           359: const char *M_Main_Key (int key)
        !           360: {
        !           361:        const char *sound = menu_move_sound;
        !           362:        switch (key)
        !           363:        {
        !           364:        case K_ESCAPE:
        !           365:                M_PopMenu ();
        !           366:                break;
        !           367: 
        !           368:        case K_KP_DOWNARROW:
        !           369:        case K_DOWNARROW:
        !           370:                if (++m_main_cursor >= MAIN_ITEMS)
        !           371:                        m_main_cursor = 0;
        !           372:                return sound;
        !           373:        case K_KP_UPARROW:
        !           374:        case K_UPARROW:
        !           375:                if (--m_main_cursor < 0)
        !           376:                        m_main_cursor = MAIN_ITEMS - 1;
        !           377:                return sound;
        !           378: 
        !           379:        case K_KP_ENTER:
        !           380:        case K_ENTER:
        !           381:                m_entersound = true;
        !           382:                switch (m_main_cursor)
        !           383:                {
        !           384:                case 0:
        !           385:                        M_Menu_Game_f ();
        !           386:                        break;
        !           387:                case 1:
        !           388:                        M_Menu_Multiplayer_f();
        !           389:                        break;
        !           390:                case 2:
        !           391:                        M_Menu_Options_f ();
        !           392:                        break;
        !           393:                case 3:
        !           394:                        M_Menu_Video_f ();
        !           395:                        break;
        !           396:                case 4:
        !           397:                        M_Menu_Quit_f ();
        !           398:                        break;
        !           399:                }
        !           400:        }
        !           401:        return NULL;
        !           402: }
        !           403: void M_Menu_Main_f (void)
        !           404: {
        !           405:        M_PushMenu (M_Main_Draw, M_Main_Key);
        !           406: }
        !           407: 
        !           408: /*
        !           409: =======================================================================
        !           410: 
        !           411: MULTIPLAYER MENU
        !           412: 
        !           413: =======================================================================
        !           414: */
        !           415: static menuframework_s s_multiplayer_menu;
        !           416: static menuaction_s            s_join_network_server_action;
        !           417: static menuaction_s            s_start_network_server_action;
        !           418: static menuaction_s            s_player_setup_action;
        !           419: 
        !           420: static void Multiplayer_MenuDraw (void)
        !           421: {
        !           422:        M_Banner( "m_banner_multiplayer" );
        !           423: 
        !           424:        Menu_AdjustCursor( &s_multiplayer_menu, 1 );
        !           425:        Menu_Draw( &s_multiplayer_menu );
        !           426: }
        !           427: 
        !           428: static void PlayerSetupFunc( void *unused )
        !           429: {
        !           430:        M_Menu_PlayerConfig_f();
        !           431: }
        !           432: 
        !           433: static void JoinNetworkServerFunc( void *unused )
        !           434: {
        !           435:        M_Menu_JoinServer_f();
        !           436: }
        !           437: 
        !           438: static void StartNetworkServerFunc( void *unused )
        !           439: {
        !           440:        M_Menu_StartServer_f ();
        !           441: }
        !           442: 
        !           443: void Multiplayer_MenuInit( void )
        !           444: {
        !           445:        s_multiplayer_menu.x = viddef.width * 0.50 - 64;
        !           446:        s_multiplayer_menu.nitems = 0;
        !           447: 
        !           448:        s_join_network_server_action.generic.type       = MTYPE_ACTION;
        !           449:        s_join_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !           450:        s_join_network_server_action.generic.x          = 0;
        !           451:        s_join_network_server_action.generic.y          = 0;
        !           452:        s_join_network_server_action.generic.name       = " join network server";
        !           453:        s_join_network_server_action.generic.callback = JoinNetworkServerFunc;
        !           454: 
        !           455:        s_start_network_server_action.generic.type      = MTYPE_ACTION;
        !           456:        s_start_network_server_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !           457:        s_start_network_server_action.generic.x         = 0;
        !           458:        s_start_network_server_action.generic.y         = 10;
        !           459:        s_start_network_server_action.generic.name      = " start network server";
        !           460:        s_start_network_server_action.generic.callback = StartNetworkServerFunc;
        !           461: 
        !           462:        s_player_setup_action.generic.type      = MTYPE_ACTION;
        !           463:        s_player_setup_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !           464:        s_player_setup_action.generic.x         = 0;
        !           465:        s_player_setup_action.generic.y         = 20;
        !           466:        s_player_setup_action.generic.name      = " player setup";
        !           467:        s_player_setup_action.generic.callback = PlayerSetupFunc;
        !           468: 
        !           469:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_join_network_server_action );
        !           470:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_start_network_server_action );
        !           471:        Menu_AddItem( &s_multiplayer_menu, ( void * ) &s_player_setup_action );
        !           472: 
        !           473:        Menu_Center( &s_multiplayer_menu );
        !           474: }
        !           475: 
        !           476: const char *Multiplayer_MenuKey( int key )
        !           477: {
        !           478:        return Default_MenuKey( &s_multiplayer_menu, key );
        !           479: }
        !           480: 
        !           481: void M_Menu_Multiplayer_f( void )
        !           482: {
        !           483:        Multiplayer_MenuInit();
        !           484:        M_PushMenu( Multiplayer_MenuDraw, Multiplayer_MenuKey );
        !           485: }
        !           486: /*
        !           487: =======================================================================
        !           488: 
        !           489: KEYS MENU
        !           490: 
        !           491: =======================================================================
        !           492: */
        !           493: char *bindnames[][2] =
        !           494: {
        !           495: {"+attack",            "attack"},
        !           496: {"weapnext",           "next weapon"},
        !           497: {"+forward",           "walk forward"},
        !           498: {"+back",                      "backpedal"},
        !           499: {"+left",                      "turn left"},
        !           500: {"+right",                     "turn right"},
        !           501: {"+speed",                     "run"},
        !           502: {"+moveleft",          "step left"},
        !           503: {"+moveright",                 "step right"},
        !           504: {"+strafe",            "sidestep"},
        !           505: {"+lookup",            "look up"},
        !           506: {"+lookdown",          "look down"},
        !           507: {"centerview",                 "center view"},
        !           508: {"+mlook",                     "mouse look"},
        !           509: {"+klook",                     "keyboard look"},
        !           510: {"+moveup",                    "up / jump"},
        !           511: {"+movedown",          "down / crouch"},
        !           512: {"inven",                      "inventory"},
        !           513: {"invuse",                     "use item"},
        !           514: {"invdrop",                    "drop item"},
        !           515: {"invprev",                    "prev item"},
        !           516: {"invnext",                    "next item"},
        !           517: {"cmd help",           "help computer" }, 
        !           518: { 0, 0 }
        !           519: };
        !           520: int                            keys_cursor;
        !           521: static int             bind_grab;
        !           522: static menuframework_s s_keys_menu;
        !           523: static menuaction_s            s_keys_attack_action;
        !           524: static menuaction_s            s_keys_change_weapon_action;
        !           525: static menuaction_s            s_keys_walk_forward_action;
        !           526: static menuaction_s            s_keys_backpedal_action;
        !           527: static menuaction_s            s_keys_turn_left_action;
        !           528: static menuaction_s            s_keys_turn_right_action;
        !           529: static menuaction_s            s_keys_run_action;
        !           530: static menuaction_s            s_keys_step_left_action;
        !           531: static menuaction_s            s_keys_step_right_action;
        !           532: static menuaction_s            s_keys_sidestep_action;
        !           533: static menuaction_s            s_keys_look_up_action;
        !           534: static menuaction_s            s_keys_look_down_action;
        !           535: static menuaction_s            s_keys_center_view_action;
        !           536: static menuaction_s            s_keys_mouse_look_action;
        !           537: static menuaction_s            s_keys_keyboard_look_action;
        !           538: static menuaction_s            s_keys_move_up_action;
        !           539: static menuaction_s            s_keys_move_down_action;
        !           540: static menuaction_s            s_keys_inventory_action;
        !           541: static menuaction_s            s_keys_inv_use_action;
        !           542: static menuaction_s            s_keys_inv_drop_action;
        !           543: static menuaction_s            s_keys_inv_prev_action;
        !           544: static menuaction_s            s_keys_inv_next_action;
        !           545: static menuaction_s            s_keys_help_computer_action;
        !           546: static void M_UnbindCommand (char *command)
        !           547: {
        !           548:        int             j;
        !           549:        int             l;
        !           550:        char    *b;
        !           551:        l = strlen(command);
        !           552:        for (j=0 ; j<256 ; j++)
        !           553:        {
        !           554:                b = keybindings[j];
        !           555:                if (!b)
        !           556:                        continue;
        !           557:                if (!strncmp (b, command, l) )
        !           558:                        Key_SetBinding (j, "");
        !           559:        }
        !           560: }
        !           561: static void M_FindKeysForCommand (char *command, int *twokeys)
        !           562: {
        !           563:        int             count;
        !           564:        int             j;
        !           565:        int             l;
        !           566:        char    *b;
        !           567:        twokeys[0] = twokeys[1] = -1;
        !           568:        l = strlen(command);
        !           569:        count = 0;
        !           570:        for (j=0 ; j<256 ; j++)
        !           571:        {
        !           572:                b = keybindings[j];
        !           573:                if (!b)
        !           574:                        continue;
        !           575:                if (!strncmp (b, command, l) )
        !           576:                {
        !           577:                        twokeys[count] = j;
        !           578:                        count++;
        !           579:                        if (count == 2)
        !           580:                                break;
        !           581:                }
        !           582:        }
        !           583: }
        !           584: static void KeyCursorDrawFunc( menuframework_s *menu )
        !           585: {
        !           586:        if ( bind_grab )
        !           587:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, '=' );
        !           588:        else
        !           589:                re.DrawChar( menu->x, menu->y + menu->cursor * 9, 12 + ( ( int ) ( Sys_Milliseconds() / 250 ) & 1 ) );
        !           590: }
        !           591: static void DrawKeyBindingFunc( void *self )
        !           592: {
        !           593:        int keys[2];
        !           594:        menuaction_s *a = ( menuaction_s * ) self;
        !           595:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys);
        !           596:                
        !           597:        if (keys[0] == -1)
        !           598:        {
        !           599:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, "???" );
        !           600:        }
        !           601:        else
        !           602:        {
        !           603:                int x;
        !           604:                const char *name;
        !           605:                name = Key_KeynumToString (keys[0]);
        !           606:                Menu_DrawString( a->generic.x + a->generic.parent->x + 16, a->generic.y + a->generic.parent->y, name );
        !           607:                x = strlen(name) * 8;
        !           608:                if (keys[1] != -1)
        !           609:                {
        !           610:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 24 + x, a->generic.y + a->generic.parent->y, "or" );
        !           611:                        Menu_DrawString( a->generic.x + a->generic.parent->x + 48 + x, a->generic.y + a->generic.parent->y, Key_KeynumToString (keys[1]) );
        !           612:                }
        !           613:        }
        !           614: }
        !           615: static void KeyBindingFunc( void *self )
        !           616: {
        !           617:        menuaction_s *a = ( menuaction_s * ) self;
        !           618:        int keys[2];
        !           619:        M_FindKeysForCommand( bindnames[a->generic.localdata[0]][0], keys );
        !           620:        if (keys[1] != -1)
        !           621:                M_UnbindCommand( bindnames[a->generic.localdata[0]][0]);
        !           622:        bind_grab = true;
        !           623:        Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
        !           624: }
        !           625: static void Keys_MenuInit( void )
        !           626: {
        !           627:        int y = 0;
        !           628:        int i = 0;
        !           629:        s_keys_menu.x = viddef.width * 0.50;
        !           630:        s_keys_menu.nitems = 0;
        !           631:        s_keys_menu.cursordraw = KeyCursorDrawFunc;
        !           632:        s_keys_attack_action.generic.type       = MTYPE_ACTION;
        !           633:        s_keys_attack_action.generic.flags  = QMF_GRAYED;
        !           634:        s_keys_attack_action.generic.x          = 0;
        !           635:        s_keys_attack_action.generic.y          = y;
        !           636:        s_keys_attack_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           637:        s_keys_attack_action.generic.localdata[0] = i;
        !           638:        s_keys_attack_action.generic.name       = bindnames[s_keys_attack_action.generic.localdata[0]][1];
        !           639:        s_keys_change_weapon_action.generic.type        = MTYPE_ACTION;
        !           640:        s_keys_change_weapon_action.generic.flags  = QMF_GRAYED;
        !           641:        s_keys_change_weapon_action.generic.x           = 0;
        !           642:        s_keys_change_weapon_action.generic.y           = y += 9;
        !           643:        s_keys_change_weapon_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           644:        s_keys_change_weapon_action.generic.localdata[0] = ++i;
        !           645:        s_keys_change_weapon_action.generic.name        = bindnames[s_keys_change_weapon_action.generic.localdata[0]][1];
        !           646:        s_keys_walk_forward_action.generic.type = MTYPE_ACTION;
        !           647:        s_keys_walk_forward_action.generic.flags  = QMF_GRAYED;
        !           648:        s_keys_walk_forward_action.generic.x            = 0;
        !           649:        s_keys_walk_forward_action.generic.y            = y += 9;
        !           650:        s_keys_walk_forward_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           651:        s_keys_walk_forward_action.generic.localdata[0] = ++i;
        !           652:        s_keys_walk_forward_action.generic.name = bindnames[s_keys_walk_forward_action.generic.localdata[0]][1];
        !           653:        s_keys_backpedal_action.generic.type    = MTYPE_ACTION;
        !           654:        s_keys_backpedal_action.generic.flags  = QMF_GRAYED;
        !           655:        s_keys_backpedal_action.generic.x               = 0;
        !           656:        s_keys_backpedal_action.generic.y               = y += 9;
        !           657:        s_keys_backpedal_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           658:        s_keys_backpedal_action.generic.localdata[0] = ++i;
        !           659:        s_keys_backpedal_action.generic.name    = bindnames[s_keys_backpedal_action.generic.localdata[0]][1];
        !           660:        s_keys_turn_left_action.generic.type    = MTYPE_ACTION;
        !           661:        s_keys_turn_left_action.generic.flags  = QMF_GRAYED;
        !           662:        s_keys_turn_left_action.generic.x               = 0;
        !           663:        s_keys_turn_left_action.generic.y               = y += 9;
        !           664:        s_keys_turn_left_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           665:        s_keys_turn_left_action.generic.localdata[0] = ++i;
        !           666:        s_keys_turn_left_action.generic.name    = bindnames[s_keys_turn_left_action.generic.localdata[0]][1];
        !           667:        s_keys_turn_right_action.generic.type   = MTYPE_ACTION;
        !           668:        s_keys_turn_right_action.generic.flags  = QMF_GRAYED;
        !           669:        s_keys_turn_right_action.generic.x              = 0;
        !           670:        s_keys_turn_right_action.generic.y              = y += 9;
        !           671:        s_keys_turn_right_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           672:        s_keys_turn_right_action.generic.localdata[0] = ++i;
        !           673:        s_keys_turn_right_action.generic.name   = bindnames[s_keys_turn_right_action.generic.localdata[0]][1];
        !           674:        s_keys_run_action.generic.type  = MTYPE_ACTION;
        !           675:        s_keys_run_action.generic.flags  = QMF_GRAYED;
        !           676:        s_keys_run_action.generic.x             = 0;
        !           677:        s_keys_run_action.generic.y             = y += 9;
        !           678:        s_keys_run_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           679:        s_keys_run_action.generic.localdata[0] = ++i;
        !           680:        s_keys_run_action.generic.name  = bindnames[s_keys_run_action.generic.localdata[0]][1];
        !           681:        s_keys_step_left_action.generic.type    = MTYPE_ACTION;
        !           682:        s_keys_step_left_action.generic.flags  = QMF_GRAYED;
        !           683:        s_keys_step_left_action.generic.x               = 0;
        !           684:        s_keys_step_left_action.generic.y               = y += 9;
        !           685:        s_keys_step_left_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           686:        s_keys_step_left_action.generic.localdata[0] = ++i;
        !           687:        s_keys_step_left_action.generic.name    = bindnames[s_keys_step_left_action.generic.localdata[0]][1];
        !           688:        s_keys_step_right_action.generic.type   = MTYPE_ACTION;
        !           689:        s_keys_step_right_action.generic.flags  = QMF_GRAYED;
        !           690:        s_keys_step_right_action.generic.x              = 0;
        !           691:        s_keys_step_right_action.generic.y              = y += 9;
        !           692:        s_keys_step_right_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           693:        s_keys_step_right_action.generic.localdata[0] = ++i;
        !           694:        s_keys_step_right_action.generic.name   = bindnames[s_keys_step_right_action.generic.localdata[0]][1];
        !           695:        s_keys_sidestep_action.generic.type     = MTYPE_ACTION;
        !           696:        s_keys_sidestep_action.generic.flags  = QMF_GRAYED;
        !           697:        s_keys_sidestep_action.generic.x                = 0;
        !           698:        s_keys_sidestep_action.generic.y                = y += 9;
        !           699:        s_keys_sidestep_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           700:        s_keys_sidestep_action.generic.localdata[0] = ++i;
        !           701:        s_keys_sidestep_action.generic.name     = bindnames[s_keys_sidestep_action.generic.localdata[0]][1];
        !           702:        s_keys_look_up_action.generic.type      = MTYPE_ACTION;
        !           703:        s_keys_look_up_action.generic.flags  = QMF_GRAYED;
        !           704:        s_keys_look_up_action.generic.x         = 0;
        !           705:        s_keys_look_up_action.generic.y         = y += 9;
        !           706:        s_keys_look_up_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           707:        s_keys_look_up_action.generic.localdata[0] = ++i;
        !           708:        s_keys_look_up_action.generic.name      = bindnames[s_keys_look_up_action.generic.localdata[0]][1];
        !           709:        s_keys_look_down_action.generic.type    = MTYPE_ACTION;
        !           710:        s_keys_look_down_action.generic.flags  = QMF_GRAYED;
        !           711:        s_keys_look_down_action.generic.x               = 0;
        !           712:        s_keys_look_down_action.generic.y               = y += 9;
        !           713:        s_keys_look_down_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           714:        s_keys_look_down_action.generic.localdata[0] = ++i;
        !           715:        s_keys_look_down_action.generic.name    = bindnames[s_keys_look_down_action.generic.localdata[0]][1];
        !           716:        s_keys_center_view_action.generic.type  = MTYPE_ACTION;
        !           717:        s_keys_center_view_action.generic.flags  = QMF_GRAYED;
        !           718:        s_keys_center_view_action.generic.x             = 0;
        !           719:        s_keys_center_view_action.generic.y             = y += 9;
        !           720:        s_keys_center_view_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           721:        s_keys_center_view_action.generic.localdata[0] = ++i;
        !           722:        s_keys_center_view_action.generic.name  = bindnames[s_keys_center_view_action.generic.localdata[0]][1];
        !           723:        s_keys_mouse_look_action.generic.type   = MTYPE_ACTION;
        !           724:        s_keys_mouse_look_action.generic.flags  = QMF_GRAYED;
        !           725:        s_keys_mouse_look_action.generic.x              = 0;
        !           726:        s_keys_mouse_look_action.generic.y              = y += 9;
        !           727:        s_keys_mouse_look_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           728:        s_keys_mouse_look_action.generic.localdata[0] = ++i;
        !           729:        s_keys_mouse_look_action.generic.name   = bindnames[s_keys_mouse_look_action.generic.localdata[0]][1];
        !           730:        s_keys_keyboard_look_action.generic.type        = MTYPE_ACTION;
        !           731:        s_keys_keyboard_look_action.generic.flags  = QMF_GRAYED;
        !           732:        s_keys_keyboard_look_action.generic.x           = 0;
        !           733:        s_keys_keyboard_look_action.generic.y           = y += 9;
        !           734:        s_keys_keyboard_look_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           735:        s_keys_keyboard_look_action.generic.localdata[0] = ++i;
        !           736:        s_keys_keyboard_look_action.generic.name        = bindnames[s_keys_keyboard_look_action.generic.localdata[0]][1];
        !           737:        s_keys_move_up_action.generic.type      = MTYPE_ACTION;
        !           738:        s_keys_move_up_action.generic.flags  = QMF_GRAYED;
        !           739:        s_keys_move_up_action.generic.x         = 0;
        !           740:        s_keys_move_up_action.generic.y         = y += 9;
        !           741:        s_keys_move_up_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           742:        s_keys_move_up_action.generic.localdata[0] = ++i;
        !           743:        s_keys_move_up_action.generic.name      = bindnames[s_keys_move_up_action.generic.localdata[0]][1];
        !           744:        s_keys_move_down_action.generic.type    = MTYPE_ACTION;
        !           745:        s_keys_move_down_action.generic.flags  = QMF_GRAYED;
        !           746:        s_keys_move_down_action.generic.x               = 0;
        !           747:        s_keys_move_down_action.generic.y               = y += 9;
        !           748:        s_keys_move_down_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           749:        s_keys_move_down_action.generic.localdata[0] = ++i;
        !           750:        s_keys_move_down_action.generic.name    = bindnames[s_keys_move_down_action.generic.localdata[0]][1];
        !           751:        s_keys_inventory_action.generic.type    = MTYPE_ACTION;
        !           752:        s_keys_inventory_action.generic.flags  = QMF_GRAYED;
        !           753:        s_keys_inventory_action.generic.x               = 0;
        !           754:        s_keys_inventory_action.generic.y               = y += 9;
        !           755:        s_keys_inventory_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           756:        s_keys_inventory_action.generic.localdata[0] = ++i;
        !           757:        s_keys_inventory_action.generic.name    = bindnames[s_keys_inventory_action.generic.localdata[0]][1];
        !           758:        s_keys_inv_use_action.generic.type      = MTYPE_ACTION;
        !           759:        s_keys_inv_use_action.generic.flags  = QMF_GRAYED;
        !           760:        s_keys_inv_use_action.generic.x         = 0;
        !           761:        s_keys_inv_use_action.generic.y         = y += 9;
        !           762:        s_keys_inv_use_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           763:        s_keys_inv_use_action.generic.localdata[0] = ++i;
        !           764:        s_keys_inv_use_action.generic.name      = bindnames[s_keys_inv_use_action.generic.localdata[0]][1];
        !           765:        s_keys_inv_drop_action.generic.type     = MTYPE_ACTION;
        !           766:        s_keys_inv_drop_action.generic.flags  = QMF_GRAYED;
        !           767:        s_keys_inv_drop_action.generic.x                = 0;
        !           768:        s_keys_inv_drop_action.generic.y                = y += 9;
        !           769:        s_keys_inv_drop_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           770:        s_keys_inv_drop_action.generic.localdata[0] = ++i;
        !           771:        s_keys_inv_drop_action.generic.name     = bindnames[s_keys_inv_drop_action.generic.localdata[0]][1];
        !           772:        s_keys_inv_prev_action.generic.type     = MTYPE_ACTION;
        !           773:        s_keys_inv_prev_action.generic.flags  = QMF_GRAYED;
        !           774:        s_keys_inv_prev_action.generic.x                = 0;
        !           775:        s_keys_inv_prev_action.generic.y                = y += 9;
        !           776:        s_keys_inv_prev_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           777:        s_keys_inv_prev_action.generic.localdata[0] = ++i;
        !           778:        s_keys_inv_prev_action.generic.name     = bindnames[s_keys_inv_prev_action.generic.localdata[0]][1];
        !           779:        s_keys_inv_next_action.generic.type     = MTYPE_ACTION;
        !           780:        s_keys_inv_next_action.generic.flags  = QMF_GRAYED;
        !           781:        s_keys_inv_next_action.generic.x                = 0;
        !           782:        s_keys_inv_next_action.generic.y                = y += 9;
        !           783:        s_keys_inv_next_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           784:        s_keys_inv_next_action.generic.localdata[0] = ++i;
        !           785:        s_keys_inv_next_action.generic.name     = bindnames[s_keys_inv_next_action.generic.localdata[0]][1];
        !           786:        s_keys_help_computer_action.generic.type        = MTYPE_ACTION;
        !           787:        s_keys_help_computer_action.generic.flags  = QMF_GRAYED;
        !           788:        s_keys_help_computer_action.generic.x           = 0;
        !           789:        s_keys_help_computer_action.generic.y           = y += 9;
        !           790:        s_keys_help_computer_action.generic.ownerdraw = DrawKeyBindingFunc;
        !           791:        s_keys_help_computer_action.generic.localdata[0] = ++i;
        !           792:        s_keys_help_computer_action.generic.name        = bindnames[s_keys_help_computer_action.generic.localdata[0]][1];
        !           793:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_attack_action );
        !           794:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_change_weapon_action );
        !           795:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_walk_forward_action );
        !           796:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_backpedal_action );
        !           797:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_left_action );
        !           798:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_turn_right_action );
        !           799:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_run_action );
        !           800:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_left_action );
        !           801:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_step_right_action );
        !           802:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_sidestep_action );
        !           803:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_up_action );
        !           804:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_look_down_action );
        !           805:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_center_view_action );
        !           806:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_mouse_look_action );
        !           807:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_keyboard_look_action );
        !           808:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_up_action );
        !           809:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_move_down_action );
        !           810:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inventory_action );
        !           811:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_use_action );
        !           812:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_drop_action );
        !           813:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_prev_action );
        !           814:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_inv_next_action );
        !           815:        Menu_AddItem( &s_keys_menu, ( void * ) &s_keys_help_computer_action );
        !           816:        
        !           817:        Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
        !           818:        Menu_Center( &s_keys_menu );
        !           819: }
        !           820: static void Keys_MenuDraw (void)
        !           821: {
        !           822:        Menu_AdjustCursor( &s_keys_menu, 1 );
        !           823:        Menu_Draw( &s_keys_menu );
        !           824: }
        !           825: static const char *Keys_MenuKey( int key )
        !           826: {
        !           827:        menuaction_s *item = ( menuaction_s * ) Menu_ItemAtCursor( &s_keys_menu );
        !           828:        if ( bind_grab )
        !           829:        {       
        !           830:                if ( key != K_ESCAPE && key != '`' )
        !           831:                {
        !           832:                        char cmd[1024];
        !           833:                        Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item->generic.localdata[0]][0]);
        !           834:                        Cbuf_InsertText (cmd);
        !           835:                }
        !           836:                
        !           837:                Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
        !           838:                bind_grab = false;
        !           839:                return menu_out_sound;
        !           840:        }
        !           841:        switch ( key )
        !           842:        {
        !           843:        case K_KP_ENTER:
        !           844:        case K_ENTER:
        !           845:                KeyBindingFunc( item );
        !           846:                return menu_in_sound;
        !           847:        case K_BACKSPACE:               // delete bindings
        !           848:        case K_DEL:                             // delete bindings
        !           849:        case K_KP_DEL:
        !           850:                M_UnbindCommand( bindnames[item->generic.localdata[0]][0] );
        !           851:                return menu_out_sound;
        !           852:        default:
        !           853:                return Default_MenuKey( &s_keys_menu, key );
        !           854:        }
        !           855: }
        !           856: void M_Menu_Keys_f (void)
        !           857: {
        !           858:        Keys_MenuInit();
        !           859:        M_PushMenu( Keys_MenuDraw, Keys_MenuKey );
        !           860: }
        !           861: /*
        !           862: =======================================================================
        !           863: CONTROLS MENU
        !           864: =======================================================================
        !           865: */
        !           866: static cvar_t *win_noalttab;
        !           867: extern cvar_t *in_joystick;
        !           868: static menuframework_s s_options_menu;
        !           869: static menuaction_s            s_options_defaults_action;
        !           870: static menuaction_s            s_options_customize_options_action;
        !           871: static menuslider_s            s_options_sensitivity_slider;
        !           872: static menulist_s              s_options_freelook_box;
        !           873: static menulist_s              s_options_noalttab_box;
        !           874: static menulist_s              s_options_alwaysrun_box;
        !           875: static menulist_s              s_options_invertmouse_box;
        !           876: static menulist_s              s_options_lookspring_box;
        !           877: static menulist_s              s_options_lookstrafe_box;
        !           878: static menulist_s              s_options_crosshair_box;
        !           879: static menuslider_s            s_options_sfxvolume_slider;
        !           880: static menulist_s              s_options_joystick_box;
        !           881: static menulist_s              s_options_cdvolume_box;
        !           882: static menulist_s              s_options_quality_list;
        !           883: static menulist_s              s_options_compatibility_list;
        !           884: static menulist_s              s_options_console_action;
        !           885: 
        !           886: static void CrosshairFunc( void *unused )
        !           887: {
        !           888:        Cvar_SetValue( "crosshair", s_options_crosshair_box.curvalue );
        !           889: }
        !           890: 
        !           891: static void JoystickFunc( void *unused )
        !           892: {
        !           893:        Cvar_SetValue( "in_joystick", s_options_joystick_box.curvalue );
        !           894: }
        !           895: static void CustomizeControlsFunc( void *unused )
        !           896: {
        !           897:        M_Menu_Keys_f();
        !           898: }
        !           899: static void AlwaysRunFunc( void *unused )
        !           900: {
        !           901:        Cvar_SetValue( "cl_run", s_options_alwaysrun_box.curvalue );
        !           902: }
        !           903: static void FreeLookFunc( void *unused )
        !           904: {
        !           905:        Cvar_SetValue( "freelook", s_options_freelook_box.curvalue );
        !           906: }
        !           907: static void MouseSpeedFunc( void *unused )
        !           908: {
        !           909:        Cvar_SetValue( "sensitivity", s_options_sensitivity_slider.curvalue / 2.0F );
        !           910: }
        !           911: static void NoAltTabFunc( void *unused )
        !           912: {
        !           913:        Cvar_SetValue( "win_noalttab", s_options_noalttab_box.curvalue );
        !           914: }
        !           915: static float ClampCvar( float min, float max, float value )
        !           916: {
        !           917:        if ( value < min ) return min;
        !           918:        if ( value > max ) return max;
        !           919:        return value;
        !           920: }
        !           921: 
        !           922: static void ControlsSetMenuItemValues( void )
        !           923: {
        !           924:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
        !           925:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
        !           926:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
        !           927:        s_options_sensitivity_slider.curvalue   = ( sensitivity->value ) * 2;
        !           928: 
        !           929:        Cvar_SetValue( "cl_run", ClampCvar( 0, 1, cl_run->value ) );
        !           930:        s_options_alwaysrun_box.curvalue                = cl_run->value;
        !           931: 
        !           932:        s_options_invertmouse_box.curvalue              = m_pitch->value < 0;
        !           933: 
        !           934:        Cvar_SetValue( "lookspring", ClampCvar( 0, 1, lookspring->value ) );
        !           935:        s_options_lookspring_box.curvalue               = lookspring->value;
        !           936: 
        !           937:        Cvar_SetValue( "lookstrafe", ClampCvar( 0, 1, lookstrafe->value ) );
        !           938:        s_options_lookstrafe_box.curvalue               = lookstrafe->value;
        !           939: 
        !           940:        Cvar_SetValue( "freelook", ClampCvar( 0, 1, freelook->value ) );
        !           941:        s_options_freelook_box.curvalue                 = freelook->value;
        !           942: 
        !           943:        Cvar_SetValue( "crosshair", ClampCvar( 0, 3, crosshair->value ) );
        !           944:        s_options_crosshair_box.curvalue                = crosshair->value;
        !           945: 
        !           946:        Cvar_SetValue( "in_joystick", ClampCvar( 0, 1, in_joystick->value ) );
        !           947:        s_options_joystick_box.curvalue         = in_joystick->value;
        !           948: 
        !           949:        s_options_noalttab_box.curvalue                 = win_noalttab->value;
        !           950: }
        !           951: static void ControlsResetDefaultsFunc( void *unused )
        !           952: {
        !           953:        Cbuf_AddText ("exec default.cfg\n");
        !           954:        Cbuf_Execute();
        !           955: 
        !           956:        ControlsSetMenuItemValues();
        !           957: }
        !           958: static void InvertMouseFunc( void *unused )
        !           959: {
        !           960:        Cvar_SetValue( "m_pitch", -m_pitch->value );
        !           961: }
        !           962: static void LookspringFunc( void *unused )
        !           963: {
        !           964:        Cvar_SetValue( "lookspring", !lookspring->value );
        !           965: }
        !           966: static void LookstrafeFunc( void *unused )
        !           967: {
        !           968:        Cvar_SetValue( "lookstrafe", !lookstrafe->value );
        !           969: }
        !           970: static void UpdateVolumeFunc( void *unused )
        !           971: {
        !           972:        Cvar_SetValue( "s_volume", s_options_sfxvolume_slider.curvalue / 10 );
        !           973: }
        !           974: 
        !           975: static void UpdateCDVolumeFunc( void *unused )
        !           976: {
        !           977:        Cvar_SetValue( "cd_nocd", !s_options_cdvolume_box.curvalue );
        !           978: }
        !           979: 
        !           980: static void ConsoleFunc( void *unused )
        !           981: {
        !           982:        /*
        !           983:        ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
        !           984:        */
        !           985:        extern void Key_ClearTyping( void );
        !           986: 
        !           987:        if ( cl.attractloop )
        !           988:        {
        !           989:                Cbuf_AddText ("killserver\n");
        !           990:                return;
        !           991:        }
        !           992: 
        !           993:        Key_ClearTyping ();
        !           994:        Con_ClearNotify ();
        !           995: 
        !           996:        M_ForceMenuOff ();
        !           997:        cls.key_dest = key_console;
        !           998: }
        !           999: 
        !          1000: static void UpdateSoundQualityFunc( void *unused )
        !          1001: {
        !          1002:        if ( s_options_quality_list.curvalue )
        !          1003:        {
        !          1004:                Cvar_SetValue( "s_khz", 22 );
        !          1005:                Cvar_SetValue( "s_loadas8bit", false );
        !          1006:        }
        !          1007:        else
        !          1008:        {
        !          1009:                Cvar_SetValue( "s_khz", 11 );
        !          1010:                Cvar_SetValue( "s_loadas8bit", true );
        !          1011:        }
        !          1012:        
        !          1013:        Cvar_SetValue( "s_primary", s_options_compatibility_list.curvalue );
        !          1014: 
        !          1015:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
        !          1016:        M_Print( 16 + 16, 120 - 48 + 8,  "Restarting the sound system. This" );
        !          1017:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
        !          1018:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
        !          1019: 
        !          1020:        // the text box won't show up unless we do a buffer swap
        !          1021:        re.EndFrame();
        !          1022: 
        !          1023:        CL_Snd_Restart_f();
        !          1024: }
        !          1025: 
        !          1026: void Options_MenuInit( void )
        !          1027: {
        !          1028:        static const char *cd_music_items[] =
        !          1029:        {
        !          1030:                "disabled",
        !          1031:                "enabled",
        !          1032:                0
        !          1033:        };
        !          1034:        static const char *quality_items[] =
        !          1035:        {
        !          1036:                "low", "high", 0
        !          1037:        };
        !          1038: 
        !          1039:        static const char *compatibility_items[] =
        !          1040:        {
        !          1041:                "max compatibility", "max performance", 0
        !          1042:        };
        !          1043: 
        !          1044:        static const char *yesno_names[] =
        !          1045:        {
        !          1046:                "no",
        !          1047:                "yes",
        !          1048:                0
        !          1049:        };
        !          1050:        static const char *crosshair_names[] =
        !          1051:        {
        !          1052:                "none",
        !          1053:                "cross",
        !          1054:                "dot",
        !          1055:                "angle",
        !          1056:                0
        !          1057:        };
        !          1058:        win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
        !          1059:        /*
        !          1060:        ** configure controls menu and menu items
        !          1061:        */
        !          1062:        s_options_menu.x = viddef.width / 2;
        !          1063:        s_options_menu.y = viddef.height / 2 - 58;
        !          1064:        s_options_menu.nitems = 0;
        !          1065: 
        !          1066:        s_options_sfxvolume_slider.generic.type = MTYPE_SLIDER;
        !          1067:        s_options_sfxvolume_slider.generic.x    = 0;
        !          1068:        s_options_sfxvolume_slider.generic.y    = 0;
        !          1069:        s_options_sfxvolume_slider.generic.name = "effects volume";
        !          1070:        s_options_sfxvolume_slider.generic.callback     = UpdateVolumeFunc;
        !          1071:        s_options_sfxvolume_slider.minvalue             = 0;
        !          1072:        s_options_sfxvolume_slider.maxvalue             = 10;
        !          1073:        s_options_sfxvolume_slider.curvalue             = Cvar_VariableValue( "s_volume" ) * 10;
        !          1074: 
        !          1075:        s_options_cdvolume_box.generic.type     = MTYPE_SPINCONTROL;
        !          1076:        s_options_cdvolume_box.generic.x                = 0;
        !          1077:        s_options_cdvolume_box.generic.y                = 10;
        !          1078:        s_options_cdvolume_box.generic.name     = "CD music";
        !          1079:        s_options_cdvolume_box.generic.callback = UpdateCDVolumeFunc;
        !          1080:        s_options_cdvolume_box.itemnames                = cd_music_items;
        !          1081:        s_options_cdvolume_box.curvalue                 = !Cvar_VariableValue("cd_nocd");
        !          1082: 
        !          1083:        s_options_quality_list.generic.type     = MTYPE_SPINCONTROL;
        !          1084:        s_options_quality_list.generic.x                = 0;
        !          1085:        s_options_quality_list.generic.y                = 20;;
        !          1086:        s_options_quality_list.generic.name             = "sound quality";
        !          1087:        s_options_quality_list.generic.callback = UpdateSoundQualityFunc;
        !          1088:        s_options_quality_list.itemnames                = quality_items;
        !          1089:        s_options_quality_list.curvalue                 = !Cvar_VariableValue( "s_loadas8bit" );
        !          1090: 
        !          1091:        s_options_compatibility_list.generic.type       = MTYPE_SPINCONTROL;
        !          1092:        s_options_compatibility_list.generic.x          = 0;
        !          1093:        s_options_compatibility_list.generic.y          = 30;
        !          1094:        s_options_compatibility_list.generic.name       = "sound compatibility";
        !          1095:        s_options_compatibility_list.generic.callback = UpdateSoundQualityFunc;
        !          1096:        s_options_compatibility_list.itemnames          = compatibility_items;
        !          1097:        s_options_compatibility_list.curvalue           = Cvar_VariableValue( "s_primary" );
        !          1098: 
        !          1099:        s_options_sensitivity_slider.generic.type       = MTYPE_SLIDER;
        !          1100:        s_options_sensitivity_slider.generic.x          = 0;
        !          1101:        s_options_sensitivity_slider.generic.y          = 50;
        !          1102:        s_options_sensitivity_slider.generic.name       = "mouse speed";
        !          1103:        s_options_sensitivity_slider.generic.callback = MouseSpeedFunc;
        !          1104:        s_options_sensitivity_slider.minvalue           = 2;
        !          1105:        s_options_sensitivity_slider.maxvalue           = 22;
        !          1106:        s_options_alwaysrun_box.generic.type = MTYPE_SPINCONTROL;
        !          1107:        s_options_alwaysrun_box.generic.x       = 0;
        !          1108:        s_options_alwaysrun_box.generic.y       = 60;
        !          1109:        s_options_alwaysrun_box.generic.name    = "always run";
        !          1110:        s_options_alwaysrun_box.generic.callback = AlwaysRunFunc;
        !          1111:        s_options_alwaysrun_box.itemnames = yesno_names;
        !          1112:        s_options_invertmouse_box.generic.type = MTYPE_SPINCONTROL;
        !          1113:        s_options_invertmouse_box.generic.x     = 0;
        !          1114:        s_options_invertmouse_box.generic.y     = 70;
        !          1115:        s_options_invertmouse_box.generic.name  = "invert mouse";
        !          1116:        s_options_invertmouse_box.generic.callback = InvertMouseFunc;
        !          1117:        s_options_invertmouse_box.itemnames = yesno_names;
        !          1118:        s_options_lookspring_box.generic.type = MTYPE_SPINCONTROL;
        !          1119:        s_options_lookspring_box.generic.x      = 0;
        !          1120:        s_options_lookspring_box.generic.y      = 80;
        !          1121:        s_options_lookspring_box.generic.name   = "lookspring";
        !          1122:        s_options_lookspring_box.generic.callback = LookspringFunc;
        !          1123:        s_options_lookspring_box.itemnames = yesno_names;
        !          1124:        s_options_lookstrafe_box.generic.type = MTYPE_SPINCONTROL;
        !          1125:        s_options_lookstrafe_box.generic.x      = 0;
        !          1126:        s_options_lookstrafe_box.generic.y      = 90;
        !          1127:        s_options_lookstrafe_box.generic.name   = "lookstrafe";
        !          1128:        s_options_lookstrafe_box.generic.callback = LookstrafeFunc;
        !          1129:        s_options_lookstrafe_box.itemnames = yesno_names;
        !          1130:        s_options_freelook_box.generic.type = MTYPE_SPINCONTROL;
        !          1131:        s_options_freelook_box.generic.x        = 0;
        !          1132:        s_options_freelook_box.generic.y        = 100;
        !          1133:        s_options_freelook_box.generic.name     = "free look";
        !          1134:        s_options_freelook_box.generic.callback = FreeLookFunc;
        !          1135:        s_options_freelook_box.itemnames = yesno_names;
        !          1136: 
        !          1137:        s_options_crosshair_box.generic.type = MTYPE_SPINCONTROL;
        !          1138:        s_options_crosshair_box.generic.x       = 0;
        !          1139:        s_options_crosshair_box.generic.y       = 110;
        !          1140:        s_options_crosshair_box.generic.name    = "crosshair";
        !          1141:        s_options_crosshair_box.generic.callback = CrosshairFunc;
        !          1142:        s_options_crosshair_box.itemnames = crosshair_names;
        !          1143: /*
        !          1144:        s_options_noalttab_box.generic.type = MTYPE_SPINCONTROL;
        !          1145:        s_options_noalttab_box.generic.x        = 0;
        !          1146:        s_options_noalttab_box.generic.y        = 110;
        !          1147:        s_options_noalttab_box.generic.name     = "disable alt-tab";
        !          1148:        s_options_noalttab_box.generic.callback = NoAltTabFunc;
        !          1149:        s_options_noalttab_box.itemnames = yesno_names;
        !          1150: */
        !          1151:        s_options_joystick_box.generic.type = MTYPE_SPINCONTROL;
        !          1152:        s_options_joystick_box.generic.x        = 0;
        !          1153:        s_options_joystick_box.generic.y        = 120;
        !          1154:        s_options_joystick_box.generic.name     = "use joystick";
        !          1155:        s_options_joystick_box.generic.callback = JoystickFunc;
        !          1156:        s_options_joystick_box.itemnames = yesno_names;
        !          1157: 
        !          1158:        s_options_customize_options_action.generic.type = MTYPE_ACTION;
        !          1159:        s_options_customize_options_action.generic.x            = 0;
        !          1160:        s_options_customize_options_action.generic.y            = 140;
        !          1161:        s_options_customize_options_action.generic.name = "customize controls";
        !          1162:        s_options_customize_options_action.generic.callback = CustomizeControlsFunc;
        !          1163:        s_options_defaults_action.generic.type  = MTYPE_ACTION;
        !          1164:        s_options_defaults_action.generic.x             = 0;
        !          1165:        s_options_defaults_action.generic.y             = 150;
        !          1166:        s_options_defaults_action.generic.name  = "reset defaults";
        !          1167:        s_options_defaults_action.generic.callback = ControlsResetDefaultsFunc;
        !          1168: 
        !          1169:        s_options_console_action.generic.type   = MTYPE_ACTION;
        !          1170:        s_options_console_action.generic.x              = 0;
        !          1171:        s_options_console_action.generic.y              = 160;
        !          1172:        s_options_console_action.generic.name   = "go to console";
        !          1173:        s_options_console_action.generic.callback = ConsoleFunc;
        !          1174: 
        !          1175:        ControlsSetMenuItemValues();
        !          1176: 
        !          1177:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sfxvolume_slider );
        !          1178:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_cdvolume_box );
        !          1179:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_quality_list );
        !          1180:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_compatibility_list );
        !          1181:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_sensitivity_slider );
        !          1182:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_alwaysrun_box );
        !          1183:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_invertmouse_box );
        !          1184:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookspring_box );
        !          1185:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_lookstrafe_box );
        !          1186:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_freelook_box );
        !          1187:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_crosshair_box );
        !          1188:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_joystick_box );
        !          1189:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_customize_options_action );
        !          1190:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_defaults_action );
        !          1191:        Menu_AddItem( &s_options_menu, ( void * ) &s_options_console_action );
        !          1192: }
        !          1193: void Options_MenuDraw (void)
        !          1194: {
        !          1195:        M_Banner( "m_banner_options" );
        !          1196:        Menu_AdjustCursor( &s_options_menu, 1 );
        !          1197:        Menu_Draw( &s_options_menu );
        !          1198: }
        !          1199: const char *Options_MenuKey( int key )
        !          1200: {
        !          1201:        return Default_MenuKey( &s_options_menu, key );
        !          1202: }
        !          1203: void M_Menu_Options_f (void)
        !          1204: {
        !          1205:        Options_MenuInit();
        !          1206:        M_PushMenu ( Options_MenuDraw, Options_MenuKey );
        !          1207: }
        !          1208: /*
        !          1209: =======================================================================
        !          1210: VIDEO MENU
        !          1211: =======================================================================
        !          1212: */
        !          1213: void M_Menu_Video_f (void)
        !          1214: {
        !          1215:        VID_MenuInit();
        !          1216:        M_PushMenu( VID_MenuDraw, VID_MenuKey );
        !          1217: }
        !          1218: /*
        !          1219: =============================================================================
        !          1220: 
        !          1221: END GAME MENU
        !          1222: 
        !          1223: =============================================================================
        !          1224: */
        !          1225: static int credits_start_time;
        !          1226: static const char *credits[] =
        !          1227: {
        !          1228:        "+QUAKE II BY ID SOFTWARE",
        !          1229:        "",
        !          1230:        "+PROGRAMMING",
        !          1231:        "John Carmack",
        !          1232:        "John Cash",
        !          1233:        "Brian Hook",
        !          1234:        "",
        !          1235:        "+ART",
        !          1236:        "Adrian Carmack",
        !          1237:        "Kevin Cloud",
        !          1238:        "Paul Steed",
        !          1239:        "",
        !          1240:        "+LEVEL DESIGN",
        !          1241:        "Tim Willits",
        !          1242:        "American McGee",
        !          1243:        "Christian Antkow",
        !          1244:        "Paul Jaquays",
        !          1245:        "Brandon James",
        !          1246:        "",
        !          1247:        "+BIZ",
        !          1248:        "Todd Hollenshead",
        !          1249:        "Barrett (Bear) Alexander",
        !          1250:        "Donna Jackson",
        !          1251:        "",
        !          1252:        "",
        !          1253:        "+SPECIAL THANKS",
        !          1254:        "Ben Donges for beta testing",
        !          1255:        "",
        !          1256:        "",
        !          1257:        "",
        !          1258:        "",
        !          1259:        "",
        !          1260:        "",
        !          1261:        "+ADDITIONAL SUPPORT",
        !          1262:        "",
        !          1263:        "+LINUX PORT AND CTF",
        !          1264:        "Dave \"Zoid\" Kirsch",
        !          1265:        "",
        !          1266:        "+CINEMATIC SEQUENCES",
        !          1267:        "Ending Cinematic by Blur Studio - ",
        !          1268:        "Venice, CA",
        !          1269:        "",
        !          1270:        "Environment models for Introduction",
        !          1271:        "Cinematic by Karl Dolgener",
        !          1272:        "",
        !          1273:        "Assistance with environment design",
        !          1274:        "by Cliff Iwai",
        !          1275:        "",
        !          1276:        "+SOUND EFFECTS AND MUSIC",
        !          1277:        "Sound Design by Soundelux Media Labs.",
        !          1278:        "Music Composed and Produced by",
        !          1279:        "Soundelux Media Labs.  Special thanks",
        !          1280:        "to Bill Brown, Tom Ozanich, Brian",
        !          1281:        "Celano, Jeff Eisner, and The Soundelux",
        !          1282:        "Players.",
        !          1283:        "",
        !          1284:        "\"Level Music\" by Sonic Mayhem",
        !          1285:        "www.sonicmayhem.com",
        !          1286:        "",
        !          1287:        "\"Quake II Theme Song\"",
        !          1288:        "(C) 1997 Rob Zombie. All Rights",
        !          1289:        "Reserved.",
        !          1290:        "",
        !          1291:        "Track 10 (\"Climb\") by Jer Sypult",
        !          1292:        "",
        !          1293:        "Voice of computers by",
        !          1294:        "Carly Staehlin-Taylor",
        !          1295:        "",
        !          1296:        "+THANKS TO ACTIVISION",
        !          1297:        "+IN PARTICULAR:",
        !          1298:        "",
        !          1299:        "John Tam",
        !          1300:        "Steve Rosenthal",
        !          1301:        "Marty Stratton",
        !          1302:        "Henk Hartong",
        !          1303:        "",
        !          1304:        "Quake II(tm) (C)1997 Id Software, Inc.",
        !          1305:        "All Rights Reserved.  Distributed by",
        !          1306:        "Activision, Inc. under license.",
        !          1307:        "Quake II(tm), the Id Software name,",
        !          1308:        "the \"Q II\"(tm) logo and id(tm)",
        !          1309:        "logo are trademarks of Id Software,",
        !          1310:        "Inc. Activision(R) is a registered",
        !          1311:        "trademark of Activision, Inc. All",
        !          1312:        "other trademarks and trade names are",
        !          1313:        "properties of their respective owners.",
        !          1314:        0
        !          1315: };
        !          1316: 
        !          1317: void M_Credits_MenuDraw( void )
        !          1318: {
        !          1319:        int i, y;
        !          1320: 
        !          1321:        /*
        !          1322:        ** draw the credits
        !          1323:        */
        !          1324:        for ( i = 0, y = viddef.height - ( ( cls.realtime - credits_start_time ) / 40.0F ); credits[i] && y < viddef.height; y += 10, i++ )
        !          1325:        {
        !          1326:                int j, stringoffset = 0;
        !          1327:                int bold = false;
        !          1328: 
        !          1329:                if ( y <= -8 )
        !          1330:                        continue;
        !          1331: 
        !          1332:                if ( credits[i][0] == '+' )
        !          1333:                {
        !          1334:                        bold = true;
        !          1335:                        stringoffset = 1;
        !          1336:                }
        !          1337:                else
        !          1338:                {
        !          1339:                        bold = false;
        !          1340:                        stringoffset = 0;
        !          1341:                }
        !          1342: 
        !          1343:                for ( j = 0; credits[i][j+stringoffset]; j++ )
        !          1344:                {
        !          1345:                        int x;
        !          1346: 
        !          1347:                        x = ( viddef.width - strlen( credits[i] ) * 8 - stringoffset * 8 ) / 2 + ( j + stringoffset ) * 8;
        !          1348: 
        !          1349:                        if ( bold )
        !          1350:                                re.DrawChar( x, y, credits[i][j+stringoffset] + 128 );
        !          1351:                        else
        !          1352:                                re.DrawChar( x, y, credits[i][j+stringoffset] );
        !          1353:                }
        !          1354:        }
        !          1355: 
        !          1356:        if ( y < 0 )
        !          1357:                credits_start_time = cls.realtime;
        !          1358: }
        !          1359: 
        !          1360: const char *M_Credits_Key( int key )
        !          1361: {
        !          1362:        switch (key)
        !          1363:        {
        !          1364:        case K_ESCAPE:
        !          1365:                M_PopMenu ();
        !          1366:                break;
        !          1367:        }
        !          1368: 
        !          1369:        return menu_out_sound;
        !          1370: 
        !          1371: }
        !          1372: 
        !          1373: void M_Menu_Credits_f( void )
        !          1374: {
        !          1375:        credits_start_time = cls.realtime;
        !          1376:        M_PushMenu( M_Credits_MenuDraw, M_Credits_Key);
        !          1377: }
        !          1378: /*
        !          1379: =============================================================================
        !          1380: 
        !          1381: GAME MENU
        !          1382: 
        !          1383: =============================================================================
        !          1384: */
        !          1385: static int             m_game_cursor;
        !          1386: static menuframework_s s_game_menu;
        !          1387: static menuaction_s            s_easy_game_action;
        !          1388: static menuaction_s            s_medium_game_action;
        !          1389: static menuaction_s            s_hard_game_action;
        !          1390: static menuaction_s            s_load_game_action;
        !          1391: static menuaction_s            s_save_game_action;
        !          1392: static menuaction_s            s_credits_action;
        !          1393: static menuseparator_s s_blankline;
        !          1394: static void StartGame( void )
        !          1395: {
        !          1396:        // disable updates and start the cinematic going
        !          1397:        cl.servercount = -1;
        !          1398:        M_ForceMenuOff ();
        !          1399:        Cvar_SetValue( "deathmatch", 0 );
        !          1400:        Cvar_SetValue( "coop", 0 );
        !          1401:        Cbuf_AddText ("loading ; killserver ; wait ; newgame\n");
        !          1402:        cls.key_dest = key_game;
        !          1403: }
        !          1404: static void EasyGameFunc( void *data )
        !          1405: {
        !          1406:        Cvar_ForceSet( "skill", "0" );
        !          1407:        StartGame();
        !          1408: }
        !          1409: static void MediumGameFunc( void *data )
        !          1410: {
        !          1411:        Cvar_ForceSet( "skill", "1" );
        !          1412:        StartGame();
        !          1413: }
        !          1414: static void HardGameFunc( void *data )
        !          1415: {
        !          1416:        Cvar_ForceSet( "skill", "2" );
        !          1417:        StartGame();
        !          1418: }
        !          1419: static void LoadGameFunc( void *unused )
        !          1420: {
        !          1421:        M_Menu_LoadGame_f ();
        !          1422: }
        !          1423: static void SaveGameFunc( void *unused )
        !          1424: {
        !          1425:        M_Menu_SaveGame_f();
        !          1426: }
        !          1427: static void CreditsFunc( void *unused )
        !          1428: {
        !          1429:        M_Menu_Credits_f();
        !          1430: }
        !          1431: void Game_MenuInit( void )
        !          1432: {
        !          1433:        static const char *difficulty_names[] =
        !          1434:        {
        !          1435:                "easy",
        !          1436:                "medium",
        !          1437:                "hard",
        !          1438:                0
        !          1439:        };
        !          1440:        s_game_menu.x = viddef.width * 0.50;
        !          1441:        s_game_menu.nitems = 0;
        !          1442:        s_easy_game_action.generic.type = MTYPE_ACTION;
        !          1443:        s_easy_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1444:        s_easy_game_action.generic.x            = 0;
        !          1445:        s_easy_game_action.generic.y            = 0;
        !          1446:        s_easy_game_action.generic.name = "easy";
        !          1447:        s_easy_game_action.generic.callback = EasyGameFunc;
        !          1448:        s_medium_game_action.generic.type       = MTYPE_ACTION;
        !          1449:        s_medium_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1450:        s_medium_game_action.generic.x          = 0;
        !          1451:        s_medium_game_action.generic.y          = 10;
        !          1452:        s_medium_game_action.generic.name       = "medium";
        !          1453:        s_medium_game_action.generic.callback = MediumGameFunc;
        !          1454:        s_hard_game_action.generic.type = MTYPE_ACTION;
        !          1455:        s_hard_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1456:        s_hard_game_action.generic.x            = 0;
        !          1457:        s_hard_game_action.generic.y            = 20;
        !          1458:        s_hard_game_action.generic.name = "hard";
        !          1459:        s_hard_game_action.generic.callback = HardGameFunc;
        !          1460:        s_blankline.generic.type = MTYPE_SEPARATOR;
        !          1461: 
        !          1462:        s_load_game_action.generic.type = MTYPE_ACTION;
        !          1463:        s_load_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1464:        s_load_game_action.generic.x            = 0;
        !          1465:        s_load_game_action.generic.y            = 40;
        !          1466:        s_load_game_action.generic.name = "load game";
        !          1467:        s_load_game_action.generic.callback = LoadGameFunc;
        !          1468:        s_save_game_action.generic.type = MTYPE_ACTION;
        !          1469:        s_save_game_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1470:        s_save_game_action.generic.x            = 0;
        !          1471:        s_save_game_action.generic.y            = 50;
        !          1472:        s_save_game_action.generic.name = "save game";
        !          1473:        s_save_game_action.generic.callback = SaveGameFunc;
        !          1474: 
        !          1475:        s_credits_action.generic.type   = MTYPE_ACTION;
        !          1476:        s_credits_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1477:        s_credits_action.generic.x              = 0;
        !          1478:        s_credits_action.generic.y              = 60;
        !          1479:        s_credits_action.generic.name   = "credits";
        !          1480:        s_credits_action.generic.callback = CreditsFunc;
        !          1481:        Menu_AddItem( &s_game_menu, ( void * ) &s_easy_game_action );
        !          1482:        Menu_AddItem( &s_game_menu, ( void * ) &s_medium_game_action );
        !          1483:        Menu_AddItem( &s_game_menu, ( void * ) &s_hard_game_action );
        !          1484:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
        !          1485:        Menu_AddItem( &s_game_menu, ( void * ) &s_load_game_action );
        !          1486:        Menu_AddItem( &s_game_menu, ( void * ) &s_save_game_action );
        !          1487:        Menu_AddItem( &s_game_menu, ( void * ) &s_blankline );
        !          1488:        Menu_AddItem( &s_game_menu, ( void * ) &s_credits_action );
        !          1489:        Menu_Center( &s_game_menu );
        !          1490: }
        !          1491: void Game_MenuDraw( void )
        !          1492: {
        !          1493:        M_Banner( "m_banner_game" );
        !          1494:        Menu_AdjustCursor( &s_game_menu, 1 );
        !          1495:        Menu_Draw( &s_game_menu );
        !          1496: }
        !          1497: const char *Game_MenuKey( int key )
        !          1498: {
        !          1499:        return Default_MenuKey( &s_game_menu, key );
        !          1500: }
        !          1501: void M_Menu_Game_f (void)
        !          1502: {
        !          1503:        Game_MenuInit();
        !          1504:        M_PushMenu( Game_MenuDraw, Game_MenuKey );
        !          1505:        m_game_cursor = 1;
        !          1506: }
        !          1507: /*
        !          1508: =============================================================================
        !          1509: LOADGAME MENU
        !          1510: =============================================================================
        !          1511: */
        !          1512: #define        MAX_SAVEGAMES   15
        !          1513: static menuframework_s s_savegame_menu;
        !          1514: static menuframework_s s_loadgame_menu;
        !          1515: static menuaction_s            s_loadgame_actions[MAX_SAVEGAMES];
        !          1516: char           m_savestrings[MAX_SAVEGAMES][32];
        !          1517: qboolean       m_savevalid[MAX_SAVEGAMES];
        !          1518: void Create_Savestrings (void)
        !          1519: {
        !          1520:        int             i;
        !          1521:        FILE    *f;
        !          1522:        char    name[MAX_OSPATH];
        !          1523:        for (i=0 ; i<MAX_SAVEGAMES ; i++)
        !          1524:        {
        !          1525:                Com_sprintf (name, sizeof(name), "%s/save/save%i/server.ssv", FS_Gamedir(), i);
        !          1526:                f = fopen (name, "rb");
        !          1527:                if (!f)
        !          1528:                {
        !          1529:                        strcpy (m_savestrings[i], "<EMPTY>");
        !          1530:                        m_savevalid[i] = false;
        !          1531:                }
        !          1532:                else
        !          1533:                {
        !          1534:                        FS_Read (m_savestrings[i], sizeof(m_savestrings[i]), f);
        !          1535:                        fclose (f);
        !          1536:                        m_savevalid[i] = true;
        !          1537:                }
        !          1538:        }
        !          1539: }
        !          1540: void LoadGameCallback( void *self )
        !          1541: {
        !          1542:        menuaction_s *a = ( menuaction_s * ) self;
        !          1543:        if ( m_savevalid[ a->generic.localdata[0] ] )
        !          1544:                Cbuf_AddText (va("load save%i\n",  a->generic.localdata[0] ) );
        !          1545:        M_ForceMenuOff ();
        !          1546: }
        !          1547: void LoadGame_MenuInit( void )
        !          1548: {
        !          1549:        int i;
        !          1550:        s_loadgame_menu.x = viddef.width / 2 - 120;
        !          1551:        s_loadgame_menu.y = viddef.height / 2 - 58;
        !          1552:        s_loadgame_menu.nitems = 0;
        !          1553:        Create_Savestrings();
        !          1554:        for ( i = 0; i < MAX_SAVEGAMES; i++ )
        !          1555:        {
        !          1556:                s_loadgame_actions[i].generic.name                      = m_savestrings[i];
        !          1557:                s_loadgame_actions[i].generic.flags                     = QMF_LEFT_JUSTIFY;
        !          1558:                s_loadgame_actions[i].generic.localdata[0]      = i;
        !          1559:                s_loadgame_actions[i].generic.callback          = LoadGameCallback;
        !          1560:                s_loadgame_actions[i].generic.x = 0;
        !          1561:                s_loadgame_actions[i].generic.y = ( i ) * 10;
        !          1562:                if (i>0)        // separate from autosave
        !          1563:                        s_loadgame_actions[i].generic.y += 10;
        !          1564:                s_loadgame_actions[i].generic.type = MTYPE_ACTION;
        !          1565:                Menu_AddItem( &s_loadgame_menu, &s_loadgame_actions[i] );
        !          1566:        }
        !          1567: }
        !          1568: void LoadGame_MenuDraw( void )
        !          1569: {
        !          1570:        M_Banner( "m_banner_load_game" );
        !          1571: //     Menu_AdjustCursor( &s_loadgame_menu, 1 );
        !          1572:        Menu_Draw( &s_loadgame_menu );
        !          1573: }
        !          1574: const char *LoadGame_MenuKey( int key )
        !          1575: {
        !          1576:        if ( key == K_ESCAPE || key == K_ENTER )
        !          1577:        {
        !          1578:                s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
        !          1579:                if ( s_savegame_menu.cursor < 0 )
        !          1580:                        s_savegame_menu.cursor = 0;
        !          1581:        }
        !          1582:        return Default_MenuKey( &s_loadgame_menu, key );
        !          1583: }
        !          1584: void M_Menu_LoadGame_f (void)
        !          1585: {
        !          1586:        LoadGame_MenuInit();
        !          1587:        M_PushMenu( LoadGame_MenuDraw, LoadGame_MenuKey );
        !          1588: }
        !          1589: /*
        !          1590: =============================================================================
        !          1591: SAVEGAME MENU
        !          1592: =============================================================================
        !          1593: */
        !          1594: static menuframework_s s_savegame_menu;
        !          1595: static menuaction_s            s_savegame_actions[MAX_SAVEGAMES];
        !          1596: void SaveGameCallback( void *self )
        !          1597: {
        !          1598:        menuaction_s *a = ( menuaction_s * ) self;
        !          1599:        Cbuf_AddText (va("save save%i\n", a->generic.localdata[0] ));
        !          1600:        M_ForceMenuOff ();
        !          1601: }
        !          1602: void SaveGame_MenuDraw( void )
        !          1603: {
        !          1604:        M_Banner( "m_banner_save_game" );
        !          1605:        Menu_AdjustCursor( &s_savegame_menu, 1 );
        !          1606:        Menu_Draw( &s_savegame_menu );
        !          1607: }
        !          1608: void SaveGame_MenuInit( void )
        !          1609: {
        !          1610:        int i;
        !          1611:        s_savegame_menu.x = viddef.width / 2 - 120;
        !          1612:        s_savegame_menu.y = viddef.height / 2 - 58;
        !          1613:        s_savegame_menu.nitems = 0;
        !          1614:        Create_Savestrings();
        !          1615:        // don't include the autosave slot
        !          1616:        for ( i = 0; i < MAX_SAVEGAMES-1; i++ )
        !          1617:        {
        !          1618:                s_savegame_actions[i].generic.name = m_savestrings[i+1];
        !          1619:                s_savegame_actions[i].generic.localdata[0] = i+1;
        !          1620:                s_savegame_actions[i].generic.flags = QMF_LEFT_JUSTIFY;
        !          1621:                s_savegame_actions[i].generic.callback = SaveGameCallback;
        !          1622:                s_savegame_actions[i].generic.x = 0;
        !          1623:                s_savegame_actions[i].generic.y = ( i ) * 10;
        !          1624:                s_savegame_actions[i].generic.type = MTYPE_ACTION;
        !          1625:                Menu_AddItem( &s_savegame_menu, &s_savegame_actions[i] );
        !          1626:        }
        !          1627: }
        !          1628: const char *SaveGame_MenuKey( int key )
        !          1629: {
        !          1630:        if ( key == K_ENTER || key == K_ESCAPE )
        !          1631:        {
        !          1632:                s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
        !          1633:                if ( s_loadgame_menu.cursor < 0 )
        !          1634:                        s_loadgame_menu.cursor = 0;
        !          1635:        }
        !          1636:        return Default_MenuKey( &s_savegame_menu, key );
        !          1637: }
        !          1638: void M_Menu_SaveGame_f (void)
        !          1639: {
        !          1640:        if (!Com_ServerState())
        !          1641:                return;         // not playing a game
        !          1642:        SaveGame_MenuInit();
        !          1643:        M_PushMenu( SaveGame_MenuDraw, SaveGame_MenuKey );
        !          1644:        Create_Savestrings ();
        !          1645: }
        !          1646: /*
        !          1647: =============================================================================
        !          1648: JOIN SERVER MENU
        !          1649: =============================================================================
        !          1650: */
        !          1651: #define MAX_LOCAL_SERVERS 8
        !          1652: static menuframework_s s_joinserver_menu;
        !          1653: static menuseparator_s s_joinserver_server_title;
        !          1654: static menuaction_s            s_joinserver_search_action;
        !          1655: static menuaction_s            s_joinserver_address_book_action;
        !          1656: static menuaction_s            s_joinserver_server_actions[MAX_LOCAL_SERVERS];
        !          1657: 
        !          1658: int            m_num_servers;
        !          1659: #define        NO_SERVER_STRING        "<no server>"
        !          1660: 
        !          1661: // user readable information
        !          1662: static char local_server_names[MAX_LOCAL_SERVERS][80];
        !          1663: 
        !          1664: // network address
        !          1665: static netadr_t local_server_netadr[MAX_LOCAL_SERVERS];
        !          1666: 
        !          1667: void M_AddToServerList (netadr_t adr, char *info)
        !          1668: {
        !          1669:        int             i;
        !          1670: 
        !          1671:        if (m_num_servers == MAX_LOCAL_SERVERS)
        !          1672:                return;
        !          1673:        while ( *info == ' ' )
        !          1674:                info++;
        !          1675: 
        !          1676:        // ignore if duplicated
        !          1677:        for (i=0 ; i<m_num_servers ; i++)
        !          1678:                if (!strcmp(info, local_server_names[i]))
        !          1679:                        return;
        !          1680: 
        !          1681:        local_server_netadr[m_num_servers] = adr;
        !          1682:        strncpy (local_server_names[m_num_servers], info, sizeof(local_server_names[0])-1);
        !          1683:        m_num_servers++;
        !          1684: }
        !          1685: 
        !          1686: void JoinServerFunc( void *self )
        !          1687: {
        !          1688:        char    buffer[128];
        !          1689:        int             index;
        !          1690: 
        !          1691:        index = ( menuaction_s * ) self - s_joinserver_server_actions;
        !          1692: 
        !          1693:        if ( Q_stricmp( local_server_names[index], NO_SERVER_STRING ) == 0 )
        !          1694:                return;
        !          1695: 
        !          1696:        if (index >= m_num_servers)
        !          1697:                return;
        !          1698: 
        !          1699:        Com_sprintf (buffer, sizeof(buffer), "connect %s\n", NET_AdrToString (local_server_netadr[index]));
        !          1700:        Cbuf_AddText (buffer);
        !          1701:        M_ForceMenuOff ();
        !          1702: }
        !          1703: void AddressBookFunc( void *self )
        !          1704: {
        !          1705:        M_Menu_AddressBook_f();
        !          1706: }
        !          1707: void NullCursorDraw( void *self )
        !          1708: {
        !          1709: }
        !          1710: 
        !          1711: void SearchLocalGames( void )
        !          1712: {
        !          1713:        int             i;
        !          1714: 
        !          1715:        m_num_servers = 0;
        !          1716:        for (i=0 ; i<MAX_LOCAL_SERVERS ; i++)
        !          1717:                strcpy (local_server_names[i], NO_SERVER_STRING);
        !          1718: 
        !          1719:        M_DrawTextBox( 8, 120 - 48, 36, 3 );
        !          1720:        M_Print( 16 + 16, 120 - 48 + 8,  "Searching for local servers, this" );
        !          1721:        M_Print( 16 + 16, 120 - 48 + 16, "could take up to a minute, so" );
        !          1722:        M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
        !          1723: 
        !          1724:        // the text box won't show up unless we do a buffer swap
        !          1725:        re.EndFrame();
        !          1726: 
        !          1727:        // send out info packets
        !          1728:        CL_PingServers_f();
        !          1729: }
        !          1730: void SearchLocalGamesFunc( void *self )
        !          1731: {
        !          1732:        SearchLocalGames();
        !          1733: }
        !          1734: void JoinServer_MenuInit( void )
        !          1735: {
        !          1736:        int i;
        !          1737:        s_joinserver_menu.x = viddef.width * 0.50 - 120;
        !          1738:        s_joinserver_menu.nitems = 0;
        !          1739:        s_joinserver_address_book_action.generic.type   = MTYPE_ACTION;
        !          1740:        s_joinserver_address_book_action.generic.name   = "address book";
        !          1741:        s_joinserver_address_book_action.generic.flags  = QMF_LEFT_JUSTIFY;
        !          1742:        s_joinserver_address_book_action.generic.x              = 0;
        !          1743:        s_joinserver_address_book_action.generic.y              = 0;
        !          1744:        s_joinserver_address_book_action.generic.callback = AddressBookFunc;
        !          1745:        s_joinserver_search_action.generic.type = MTYPE_ACTION;
        !          1746:        s_joinserver_search_action.generic.name = "refresh server list";
        !          1747:        s_joinserver_search_action.generic.flags        = QMF_LEFT_JUSTIFY;
        !          1748:        s_joinserver_search_action.generic.x    = 0;
        !          1749:        s_joinserver_search_action.generic.y    = 10;
        !          1750:        s_joinserver_search_action.generic.callback = SearchLocalGamesFunc;
        !          1751:        s_joinserver_search_action.generic.statusbar = "search for servers";
        !          1752:        s_joinserver_server_title.generic.type = MTYPE_SEPARATOR;
        !          1753:        s_joinserver_server_title.generic.name = "connect to...";
        !          1754:        s_joinserver_server_title.generic.x    = 80;
        !          1755:        s_joinserver_server_title.generic.y        = 30;
        !          1756:        for ( i = 0; i < MAX_LOCAL_SERVERS; i++ )
        !          1757:        {
        !          1758:                s_joinserver_server_actions[i].generic.type     = MTYPE_ACTION;
        !          1759:                strcpy (local_server_names[i], NO_SERVER_STRING);
        !          1760:                s_joinserver_server_actions[i].generic.name     = local_server_names[i];
        !          1761:                s_joinserver_server_actions[i].generic.flags    = QMF_LEFT_JUSTIFY;
        !          1762:                s_joinserver_server_actions[i].generic.x                = 0;
        !          1763:                s_joinserver_server_actions[i].generic.y                = 40 + i*10;
        !          1764:                s_joinserver_server_actions[i].generic.callback = JoinServerFunc;
        !          1765:                s_joinserver_server_actions[i].generic.statusbar = "press ENTER to connect";
        !          1766:        }
        !          1767:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_address_book_action );
        !          1768:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_title );
        !          1769:        Menu_AddItem( &s_joinserver_menu, &s_joinserver_search_action );
        !          1770:        for ( i = 0; i < 8; i++ )
        !          1771:                Menu_AddItem( &s_joinserver_menu, &s_joinserver_server_actions[i] );
        !          1772:        Menu_Center( &s_joinserver_menu );
        !          1773: 
        !          1774:        SearchLocalGames();
        !          1775: }
        !          1776: void JoinServer_MenuDraw(void)
        !          1777: {
        !          1778:        M_Banner( "m_banner_join_server" );
        !          1779:        Menu_Draw( &s_joinserver_menu );
        !          1780: }
        !          1781: const char *JoinServer_MenuKey( int key )
        !          1782: {
        !          1783:        return Default_MenuKey( &s_joinserver_menu, key );
        !          1784: }
        !          1785: void M_Menu_JoinServer_f (void)
        !          1786: {
        !          1787:        JoinServer_MenuInit();
        !          1788:        M_PushMenu( JoinServer_MenuDraw, JoinServer_MenuKey );
        !          1789: }
        !          1790: 
        !          1791: /*
        !          1792: =============================================================================
        !          1793: START SERVER MENU
        !          1794: =============================================================================
        !          1795: */
        !          1796: static menuframework_s s_startserver_menu;
        !          1797: static char **mapnames;
        !          1798: static int       nummaps;
        !          1799: static menuaction_s    s_startserver_start_action;
        !          1800: static menuaction_s    s_startserver_dmoptions_action;
        !          1801: static menufield_s     s_timelimit_field;
        !          1802: static menufield_s     s_fraglimit_field;
        !          1803: static menufield_s     s_maxclients_field;
        !          1804: static menufield_s     s_hostname_field;
        !          1805: static menulist_s      s_startmap_list;
        !          1806: static menulist_s      s_rules_box;
        !          1807: 
        !          1808: void DMOptionsFunc( void *self )
        !          1809: {
        !          1810:        if (s_rules_box.curvalue == 1)
        !          1811:                return;
        !          1812:        M_Menu_DMOptions_f();
        !          1813: }
        !          1814: 
        !          1815: void RulesChangeFunc ( void *self )
        !          1816: {
        !          1817:        // DM
        !          1818:        if (s_rules_box.curvalue == 0)
        !          1819:        {
        !          1820:                s_maxclients_field.generic.statusbar = NULL;
        !          1821:                s_startserver_dmoptions_action.generic.statusbar = NULL;
        !          1822:        }
        !          1823:        else // coop
        !          1824:        {
        !          1825:                s_maxclients_field.generic.statusbar = "4 maximum for cooperative";
        !          1826:                if (atoi(s_maxclients_field.buffer) > 4)
        !          1827:                        strcpy( s_maxclients_field.buffer, "4" );
        !          1828:                s_startserver_dmoptions_action.generic.statusbar = "N/A for cooperative";
        !          1829:        }
        !          1830: }
        !          1831: void StartServerActionFunc( void *self )
        !          1832: {
        !          1833:        char    startmap[1024];
        !          1834:        int             timelimit;
        !          1835:        int             fraglimit;
        !          1836:        int             maxclients;
        !          1837:        char    *spot;
        !          1838:        strcpy( startmap, strchr( mapnames[s_startmap_list.curvalue], '\n' ) + 1 );
        !          1839: 
        !          1840:        maxclients  = atoi( s_maxclients_field.buffer );
        !          1841:        timelimit       = atoi( s_timelimit_field.buffer );
        !          1842:        fraglimit       = atoi( s_fraglimit_field.buffer );
        !          1843: 
        !          1844:        Cvar_SetValue( "maxclients", ClampCvar( 0, maxclients, maxclients ) );
        !          1845:        Cvar_SetValue ("timelimit", ClampCvar( 0, timelimit, timelimit ) );
        !          1846:        Cvar_SetValue ("fraglimit", ClampCvar( 0, fraglimit, fraglimit ) );
        !          1847:        Cvar_Set("hostname", s_hostname_field.buffer );
        !          1848:        Cvar_SetValue ("deathmatch", !s_rules_box.curvalue );
        !          1849:        Cvar_SetValue ("coop", s_rules_box.curvalue );
        !          1850: 
        !          1851:        spot = NULL;
        !          1852:        if (s_rules_box.curvalue)
        !          1853:        {
        !          1854:                if(stricmp(startmap, "bunk1") == 0)
        !          1855:                        spot = "start";
        !          1856:                else if(stricmp(startmap, "mintro") == 0)
        !          1857:                        spot = "start";
        !          1858:                else if(stricmp(startmap, "fact1") == 0)
        !          1859:                        spot = "start";
        !          1860:                else if(stricmp(startmap, "power1") == 0)
        !          1861:                        spot = "pstart";
        !          1862:                else if(stricmp(startmap, "biggun") == 0)
        !          1863:                        spot = "bstart";
        !          1864:                else if(stricmp(startmap, "hangar1") == 0)
        !          1865:                        spot = "unitstart";
        !          1866:                else if(stricmp(startmap, "city1") == 0)
        !          1867:                        spot = "unitstart";
        !          1868:                else if(stricmp(startmap, "boss1") == 0)
        !          1869:                        spot = "bosstart";
        !          1870:        }
        !          1871: 
        !          1872:        if (spot)
        !          1873:        {
        !          1874:                if (Com_ServerState())
        !          1875:                        Cbuf_AddText ("disconnect\n");
        !          1876:                Cbuf_AddText (va("gamemap \"*%s$%s\"\n", startmap, spot));
        !          1877:        }
        !          1878:        else
        !          1879:        {
        !          1880:                Cbuf_AddText (va("map %s\n", startmap));
        !          1881:        }
        !          1882: 
        !          1883:        M_ForceMenuOff ();
        !          1884: }
        !          1885: 
        !          1886: void StartServer_MenuInit( void )
        !          1887: {
        !          1888:        static const char *dm_coop_names[] =
        !          1889:        {
        !          1890:                "deathmatch",
        !          1891:                "cooperative",
        !          1892:                0
        !          1893:        };
        !          1894:        char *buffer;
        !          1895:        char  mapsname[1024];
        !          1896:        char *s;
        !          1897:        int length;
        !          1898:        int i;
        !          1899:        FILE *fp;
        !          1900: 
        !          1901:        /*
        !          1902:        ** load the list of map names
        !          1903:        */
        !          1904:        Com_sprintf( mapsname, sizeof( mapsname ), "%s/maps.lst", FS_Gamedir() );
        !          1905:        if ( ( fp = fopen( mapsname, "rb" ) ) == 0 )
        !          1906:        {
        !          1907:                if ( ( length = FS_LoadFile( "maps.lst", ( void ** ) &buffer ) ) == -1 )
        !          1908:                        Com_Error( ERR_DROP, "couldn't find maps.lst\n" );
        !          1909:        }
        !          1910:        else
        !          1911:        {
        !          1912:                length = filelength( fileno( fp  ) );
        !          1913:                buffer = malloc( length );
        !          1914:                fread( buffer, length, 1, fp );
        !          1915:        }
        !          1916: 
        !          1917:        s = buffer;
        !          1918: 
        !          1919:        i = 0;
        !          1920:        while ( i < length )
        !          1921:        {
        !          1922:                if ( s[i] == '\r' )
        !          1923:                        nummaps++;
        !          1924:                i++;
        !          1925:        }
        !          1926: 
        !          1927:        if ( nummaps == 0 )
        !          1928:                Com_Error( ERR_DROP, "no maps in maps.lst\n" );
        !          1929: 
        !          1930:        mapnames = malloc( sizeof( char * ) * ( nummaps + 1 ) );
        !          1931:        memset( mapnames, 0, sizeof( char * ) * ( nummaps + 1 ) );
        !          1932: 
        !          1933:        s = buffer;
        !          1934: 
        !          1935:        for ( i = 0; i < nummaps; i++ )
        !          1936:        {
        !          1937:     char  shortname[MAX_TOKEN_CHARS];
        !          1938:     char  longname[MAX_TOKEN_CHARS];
        !          1939:                char  scratch[200];
        !          1940:                int             j, l;
        !          1941: 
        !          1942:                strcpy( shortname, COM_Parse( &s ) );
        !          1943:                l = strlen(shortname);
        !          1944:                for (j=0 ; j<l ; j++)
        !          1945:                        shortname[j] = toupper(shortname[j]);
        !          1946:                strcpy( longname, COM_Parse( &s ) );
        !          1947:                Com_sprintf( scratch, sizeof( scratch ), "%s\n%s", longname, shortname );
        !          1948: 
        !          1949:                mapnames[i] = malloc( strlen( scratch ) + 1 );
        !          1950:                strcpy( mapnames[i], scratch );
        !          1951:        }
        !          1952:        mapnames[nummaps] = 0;
        !          1953: 
        !          1954:        if ( fp != 0 )
        !          1955:        {
        !          1956:                fp = 0;
        !          1957:                free( buffer );
        !          1958:        }
        !          1959:        else
        !          1960:        {
        !          1961:                FS_FreeFile( buffer );
        !          1962:        }
        !          1963: 
        !          1964:        /*
        !          1965:        ** initialize the menu stuff
        !          1966:        */
        !          1967:        s_startserver_menu.x = viddef.width * 0.50;
        !          1968:        s_startserver_menu.nitems = 0;
        !          1969:        s_startmap_list.generic.type = MTYPE_SPINCONTROL;
        !          1970:        s_startmap_list.generic.x       = 0;
        !          1971:        s_startmap_list.generic.y       = 0;
        !          1972:        s_startmap_list.generic.name    = "initial map";
        !          1973:        s_startmap_list.itemnames = mapnames;
        !          1974:        s_rules_box.generic.type = MTYPE_SPINCONTROL;
        !          1975:        s_rules_box.generic.x   = 0;
        !          1976:        s_rules_box.generic.y   = 20;
        !          1977:        s_rules_box.generic.name        = "rules";
        !          1978:        s_rules_box.itemnames = dm_coop_names;
        !          1979:        if (Cvar_VariableValue("coop"))
        !          1980:                s_rules_box.curvalue = 1;
        !          1981:        else
        !          1982:                s_rules_box.curvalue = 0;
        !          1983:        s_rules_box.generic.callback = RulesChangeFunc;
        !          1984:        s_timelimit_field.generic.type = MTYPE_FIELD;
        !          1985:        s_timelimit_field.generic.name = "time limit";
        !          1986:        s_timelimit_field.generic.flags = QMF_NUMBERSONLY;
        !          1987:        s_timelimit_field.generic.x     = 0;
        !          1988:        s_timelimit_field.generic.y     = 36;
        !          1989:        s_timelimit_field.generic.statusbar = "0 = no limit";
        !          1990:        s_timelimit_field.length = 3;
        !          1991:        s_timelimit_field.visible_length = 3;
        !          1992:        strcpy( s_timelimit_field.buffer, Cvar_VariableString("timelimit") );
        !          1993:        s_fraglimit_field.generic.type = MTYPE_FIELD;
        !          1994:        s_fraglimit_field.generic.name = "frag limit";
        !          1995:        s_fraglimit_field.generic.flags = QMF_NUMBERSONLY;
        !          1996:        s_fraglimit_field.generic.x     = 0;
        !          1997:        s_fraglimit_field.generic.y     = 54;
        !          1998:        s_fraglimit_field.generic.statusbar = "0 = no limit";
        !          1999:        s_fraglimit_field.length = 3;
        !          2000:        s_fraglimit_field.visible_length = 3;
        !          2001:        strcpy( s_fraglimit_field.buffer, Cvar_VariableString("fraglimit") );
        !          2002: 
        !          2003:        /*
        !          2004:        ** maxclients determines the maximum number of players that can join
        !          2005:        ** the game.  If maxclients is only "1" then we should default the menu
        !          2006:        ** option to 8 players, otherwise use whatever its current value is. 
        !          2007:        ** Clamping will be done when the server is actually started.
        !          2008:        */
        !          2009:        s_maxclients_field.generic.type = MTYPE_FIELD;
        !          2010:        s_maxclients_field.generic.name = "max players";
        !          2011:        s_maxclients_field.generic.flags = QMF_NUMBERSONLY;
        !          2012:        s_maxclients_field.generic.x    = 0;
        !          2013:        s_maxclients_field.generic.y    = 72;
        !          2014:        s_maxclients_field.generic.statusbar = NULL;
        !          2015:        s_maxclients_field.length = 3;
        !          2016:        s_maxclients_field.visible_length = 3;
        !          2017:        if ( Cvar_VariableValue( "maxclients" ) == 1 )
        !          2018:                strcpy( s_maxclients_field.buffer, "8" );
        !          2019:        else 
        !          2020:                strcpy( s_maxclients_field.buffer, Cvar_VariableString("maxclients") );
        !          2021: 
        !          2022:        s_hostname_field.generic.type = MTYPE_FIELD;
        !          2023:        s_hostname_field.generic.name = "hostname";
        !          2024:        s_hostname_field.generic.flags = 0;
        !          2025:        s_hostname_field.generic.x      = 0;
        !          2026:        s_hostname_field.generic.y      = 90;
        !          2027:        s_hostname_field.generic.statusbar = NULL;
        !          2028:        s_hostname_field.length = 12;
        !          2029:        s_hostname_field.visible_length = 12;
        !          2030:        strcpy( s_hostname_field.buffer, Cvar_VariableString("hostname") );
        !          2031: 
        !          2032:        s_startserver_dmoptions_action.generic.type = MTYPE_ACTION;
        !          2033:        s_startserver_dmoptions_action.generic.name     = " deathmatch flags";
        !          2034:        s_startserver_dmoptions_action.generic.flags= QMF_LEFT_JUSTIFY;
        !          2035:        s_startserver_dmoptions_action.generic.x        = 24;
        !          2036:        s_startserver_dmoptions_action.generic.y        = 108;
        !          2037:        s_startserver_dmoptions_action.generic.statusbar = NULL;
        !          2038:        s_startserver_dmoptions_action.generic.callback = DMOptionsFunc;
        !          2039: 
        !          2040:        s_startserver_start_action.generic.type = MTYPE_ACTION;
        !          2041:        s_startserver_start_action.generic.name = " begin";
        !          2042:        s_startserver_start_action.generic.flags= QMF_LEFT_JUSTIFY;
        !          2043:        s_startserver_start_action.generic.x    = 24;
        !          2044:        s_startserver_start_action.generic.y    = 128;
        !          2045:        s_startserver_start_action.generic.callback = StartServerActionFunc;
        !          2046: 
        !          2047:        Menu_AddItem( &s_startserver_menu, &s_startmap_list );
        !          2048:        Menu_AddItem( &s_startserver_menu, &s_rules_box );
        !          2049:        Menu_AddItem( &s_startserver_menu, &s_timelimit_field );
        !          2050:        Menu_AddItem( &s_startserver_menu, &s_fraglimit_field );
        !          2051:        Menu_AddItem( &s_startserver_menu, &s_maxclients_field );
        !          2052:        Menu_AddItem( &s_startserver_menu, &s_hostname_field );
        !          2053:        Menu_AddItem( &s_startserver_menu, &s_startserver_dmoptions_action );
        !          2054:        Menu_AddItem( &s_startserver_menu, &s_startserver_start_action );
        !          2055: 
        !          2056:        Menu_Center( &s_startserver_menu );
        !          2057: 
        !          2058:        // call this now to set proper inital state
        !          2059:        RulesChangeFunc ( NULL );
        !          2060: }
        !          2061: void StartServer_MenuDraw(void)
        !          2062: {
        !          2063:        Menu_Draw( &s_startserver_menu );
        !          2064: }
        !          2065: const char *StartServer_MenuKey( int key )
        !          2066: {
        !          2067:        if ( key == K_ESCAPE )
        !          2068:        {
        !          2069:                if ( mapnames )
        !          2070:                {
        !          2071:                        int i;
        !          2072: 
        !          2073:                        for ( i = 0; i < nummaps; i++ )
        !          2074:                                free( mapnames[i] );
        !          2075:                        free( mapnames );
        !          2076:                }
        !          2077:                mapnames = 0;
        !          2078:                nummaps = 0;
        !          2079:        }
        !          2080:        return Default_MenuKey( &s_startserver_menu, key );
        !          2081: }
        !          2082: void M_Menu_StartServer_f (void)
        !          2083: {
        !          2084:        StartServer_MenuInit();
        !          2085:        M_PushMenu( StartServer_MenuDraw, StartServer_MenuKey );
        !          2086: }
        !          2087: /*
        !          2088: =============================================================================
        !          2089: 
        !          2090: DMOPTIONS BOOK MENU
        !          2091: 
        !          2092: =============================================================================
        !          2093: */
        !          2094: static char dmoptions_statusbar[128];
        !          2095: 
        !          2096: static menuframework_s s_dmoptions_menu;
        !          2097: 
        !          2098: static menulist_s      s_friendlyfire_box;
        !          2099: static menulist_s      s_falls_box;
        !          2100: static menulist_s      s_weapons_stay_box;
        !          2101: static menulist_s      s_instant_powerups_box;
        !          2102: static menulist_s      s_powerups_box;
        !          2103: static menulist_s      s_health_box;
        !          2104: static menulist_s      s_spawn_farthest_box;
        !          2105: static menulist_s      s_teamplay_box;
        !          2106: static menulist_s      s_samelevel_box;
        !          2107: static menulist_s      s_force_respawn_box;
        !          2108: static menulist_s      s_armor_box;
        !          2109: static menulist_s      s_allow_exit_box;
        !          2110: static menulist_s      s_infinite_ammo_box;
        !          2111: static menulist_s      s_fixed_fov_box;
        !          2112: static menulist_s      s_quad_drop_box;
        !          2113: 
        !          2114: static void DMFlagCallback( void *self )
        !          2115: {
        !          2116:        menulist_s *f = ( menulist_s * ) self;
        !          2117:        int flags;
        !          2118:        int bit = 0;
        !          2119: 
        !          2120:        flags = Cvar_VariableValue( "dmflags" );
        !          2121: 
        !          2122:        if ( f == &s_friendlyfire_box )
        !          2123:        {
        !          2124:                if ( f->curvalue )
        !          2125:                        flags &= ~DF_NO_FRIENDLY_FIRE;
        !          2126:                else
        !          2127:                        flags |= DF_NO_FRIENDLY_FIRE;
        !          2128:                goto setvalue;
        !          2129:        }
        !          2130:        else if ( f == &s_falls_box )
        !          2131:        {
        !          2132:                if ( f->curvalue )
        !          2133:                        flags &= ~DF_NO_FALLING;
        !          2134:                else
        !          2135:                        flags |= DF_NO_FALLING;
        !          2136:                goto setvalue;
        !          2137:        }
        !          2138:        else if ( f == &s_weapons_stay_box ) 
        !          2139:        {
        !          2140:                bit = DF_WEAPONS_STAY;
        !          2141:        }
        !          2142:        else if ( f == &s_instant_powerups_box )
        !          2143:        {
        !          2144:                bit = DF_INSTANT_ITEMS;
        !          2145:        }
        !          2146:        else if ( f == &s_allow_exit_box )
        !          2147:        {
        !          2148:                bit = DF_ALLOW_EXIT;
        !          2149:        }
        !          2150:        else if ( f == &s_powerups_box )
        !          2151:        {
        !          2152:                if ( f->curvalue )
        !          2153:                        flags &= ~DF_NO_ITEMS;
        !          2154:                else
        !          2155:                        flags |= DF_NO_ITEMS;
        !          2156:                goto setvalue;
        !          2157:        }
        !          2158:        else if ( f == &s_health_box )
        !          2159:        {
        !          2160:                if ( f->curvalue )
        !          2161:                        flags &= ~DF_NO_HEALTH;
        !          2162:                else
        !          2163:                        flags |= DF_NO_HEALTH;
        !          2164:                goto setvalue;
        !          2165:        }
        !          2166:        else if ( f == &s_spawn_farthest_box )
        !          2167:        {
        !          2168:                bit = DF_SPAWN_FARTHEST;
        !          2169:        }
        !          2170:        else if ( f == &s_teamplay_box )
        !          2171:        {
        !          2172:                if ( f->curvalue == 1 )
        !          2173:                {
        !          2174:                        flags |=  DF_SKINTEAMS;
        !          2175:                        flags &= ~DF_MODELTEAMS;
        !          2176:                }
        !          2177:                else if ( f->curvalue == 2 )
        !          2178:                {
        !          2179:                        flags |=  DF_MODELTEAMS;
        !          2180:                        flags &= ~DF_SKINTEAMS;
        !          2181:                }
        !          2182:                else
        !          2183:                {
        !          2184:                        flags &= ~( DF_MODELTEAMS | DF_SKINTEAMS );
        !          2185:                }
        !          2186: 
        !          2187:                goto setvalue;
        !          2188:        }
        !          2189:        else if ( f == &s_samelevel_box )
        !          2190:        {
        !          2191:                bit = DF_SAME_LEVEL;
        !          2192:        }
        !          2193:        else if ( f == &s_force_respawn_box )
        !          2194:        {
        !          2195:                bit = DF_FORCE_RESPAWN;
        !          2196:        }
        !          2197:        else if ( f == &s_armor_box )
        !          2198:        {
        !          2199:                if ( f->curvalue )
        !          2200:                        flags &= ~DF_NO_ARMOR;
        !          2201:                else
        !          2202:                        flags |= DF_NO_ARMOR;
        !          2203:                goto setvalue;
        !          2204:        }
        !          2205:        else if ( f == &s_infinite_ammo_box )
        !          2206:        {
        !          2207:                bit = DF_INFINITE_AMMO;
        !          2208:        }
        !          2209:        else if ( f == &s_fixed_fov_box )
        !          2210:        {
        !          2211:                bit = DF_FIXED_FOV;
        !          2212:        }
        !          2213:        else if ( f == &s_quad_drop_box )
        !          2214:        {
        !          2215:                bit = DF_QUAD_DROP;
        !          2216:        }
        !          2217: 
        !          2218: 
        !          2219:        if ( f )
        !          2220:        {
        !          2221:                if ( f->curvalue == 0 )
        !          2222:                        flags &= ~bit;
        !          2223:                else
        !          2224:                        flags |= bit;
        !          2225:        }
        !          2226: 
        !          2227: setvalue:
        !          2228:        Cvar_SetValue ("dmflags", flags);
        !          2229: 
        !          2230:        Com_sprintf( dmoptions_statusbar, sizeof( dmoptions_statusbar ), "dmflags = %d", flags );
        !          2231: 
        !          2232: }
        !          2233: 
        !          2234: void DMOptions_MenuInit( void )
        !          2235: {
        !          2236:        static const char *yes_no_names[] =
        !          2237:        {
        !          2238:                "no", "yes", 0
        !          2239:        };
        !          2240:        static const char *teamplay_names[] = 
        !          2241:        {
        !          2242:                "disabled", "by skin", "by model", 0
        !          2243:        };
        !          2244:        int dmflags = Cvar_VariableValue( "dmflags" );
        !          2245:        int y = 0;
        !          2246: 
        !          2247:        s_dmoptions_menu.x = viddef.width * 0.50;
        !          2248:        s_dmoptions_menu.nitems = 0;
        !          2249: 
        !          2250:        s_falls_box.generic.type = MTYPE_SPINCONTROL;
        !          2251:        s_falls_box.generic.x   = 0;
        !          2252:        s_falls_box.generic.y   = y;
        !          2253:        s_falls_box.generic.name        = "falling damage";
        !          2254:        s_falls_box.generic.callback = DMFlagCallback;
        !          2255:        s_falls_box.itemnames = yes_no_names;
        !          2256:        s_falls_box.curvalue = ( dmflags & DF_NO_FALLING ) == 0;
        !          2257: 
        !          2258:        s_weapons_stay_box.generic.type = MTYPE_SPINCONTROL;
        !          2259:        s_weapons_stay_box.generic.x    = 0;
        !          2260:        s_weapons_stay_box.generic.y    = y += 10;
        !          2261:        s_weapons_stay_box.generic.name = "weapons stay";
        !          2262:        s_weapons_stay_box.generic.callback = DMFlagCallback;
        !          2263:        s_weapons_stay_box.itemnames = yes_no_names;
        !          2264:        s_weapons_stay_box.curvalue = ( dmflags & DF_WEAPONS_STAY ) != 0;
        !          2265: 
        !          2266:        s_instant_powerups_box.generic.type = MTYPE_SPINCONTROL;
        !          2267:        s_instant_powerups_box.generic.x        = 0;
        !          2268:        s_instant_powerups_box.generic.y        = y += 10;
        !          2269:        s_instant_powerups_box.generic.name     = "instant powerups";
        !          2270:        s_instant_powerups_box.generic.callback = DMFlagCallback;
        !          2271:        s_instant_powerups_box.itemnames = yes_no_names;
        !          2272:        s_instant_powerups_box.curvalue = ( dmflags & DF_INSTANT_ITEMS ) != 0;
        !          2273: 
        !          2274:        s_powerups_box.generic.type = MTYPE_SPINCONTROL;
        !          2275:        s_powerups_box.generic.x        = 0;
        !          2276:        s_powerups_box.generic.y        = y += 10;
        !          2277:        s_powerups_box.generic.name     = "allow powerups";
        !          2278:        s_powerups_box.generic.callback = DMFlagCallback;
        !          2279:        s_powerups_box.itemnames = yes_no_names;
        !          2280:        s_powerups_box.curvalue = ( dmflags & DF_NO_ITEMS ) == 0;
        !          2281: 
        !          2282:        s_health_box.generic.type = MTYPE_SPINCONTROL;
        !          2283:        s_health_box.generic.x  = 0;
        !          2284:        s_health_box.generic.y  = y += 10;
        !          2285:        s_health_box.generic.callback = DMFlagCallback;
        !          2286:        s_health_box.generic.name       = "allow health";
        !          2287:        s_health_box.itemnames = yes_no_names;
        !          2288:        s_health_box.curvalue = ( dmflags & DF_NO_HEALTH ) == 0;
        !          2289: 
        !          2290:        s_armor_box.generic.type = MTYPE_SPINCONTROL;
        !          2291:        s_armor_box.generic.x   = 0;
        !          2292:        s_armor_box.generic.y   = y += 10;
        !          2293:        s_armor_box.generic.name        = "allow armor";
        !          2294:        s_armor_box.generic.callback = DMFlagCallback;
        !          2295:        s_armor_box.itemnames = yes_no_names;
        !          2296:        s_armor_box.curvalue = ( dmflags & DF_NO_ARMOR ) == 0;
        !          2297: 
        !          2298:        s_spawn_farthest_box.generic.type = MTYPE_SPINCONTROL;
        !          2299:        s_spawn_farthest_box.generic.x  = 0;
        !          2300:        s_spawn_farthest_box.generic.y  = y += 10;
        !          2301:        s_spawn_farthest_box.generic.name       = "spawn farthest";
        !          2302:        s_spawn_farthest_box.generic.callback = DMFlagCallback;
        !          2303:        s_spawn_farthest_box.itemnames = yes_no_names;
        !          2304:        s_spawn_farthest_box.curvalue = ( dmflags & DF_SPAWN_FARTHEST ) != 0;
        !          2305: 
        !          2306:        s_samelevel_box.generic.type = MTYPE_SPINCONTROL;
        !          2307:        s_samelevel_box.generic.x       = 0;
        !          2308:        s_samelevel_box.generic.y       = y += 10;
        !          2309:        s_samelevel_box.generic.name    = "same map";
        !          2310:        s_samelevel_box.generic.callback = DMFlagCallback;
        !          2311:        s_samelevel_box.itemnames = yes_no_names;
        !          2312:        s_samelevel_box.curvalue = ( dmflags & DF_SAME_LEVEL ) != 0;
        !          2313: 
        !          2314:        s_force_respawn_box.generic.type = MTYPE_SPINCONTROL;
        !          2315:        s_force_respawn_box.generic.x   = 0;
        !          2316:        s_force_respawn_box.generic.y   = y += 10;
        !          2317:        s_force_respawn_box.generic.name        = "force respawn";
        !          2318:        s_force_respawn_box.generic.callback = DMFlagCallback;
        !          2319:        s_force_respawn_box.itemnames = yes_no_names;
        !          2320:        s_force_respawn_box.curvalue = ( dmflags & DF_FORCE_RESPAWN ) != 0;
        !          2321: 
        !          2322:        s_teamplay_box.generic.type = MTYPE_SPINCONTROL;
        !          2323:        s_teamplay_box.generic.x        = 0;
        !          2324:        s_teamplay_box.generic.y        = y += 10;
        !          2325:        s_teamplay_box.generic.name     = "teamplay";
        !          2326:        s_teamplay_box.generic.callback = DMFlagCallback;
        !          2327:        s_teamplay_box.itemnames = teamplay_names;
        !          2328: 
        !          2329:        s_allow_exit_box.generic.type = MTYPE_SPINCONTROL;
        !          2330:        s_allow_exit_box.generic.x      = 0;
        !          2331:        s_allow_exit_box.generic.y      = y += 10;
        !          2332:        s_allow_exit_box.generic.name   = "allow exit";
        !          2333:        s_allow_exit_box.generic.callback = DMFlagCallback;
        !          2334:        s_allow_exit_box.itemnames = yes_no_names;
        !          2335:        s_allow_exit_box.curvalue = ( dmflags & DF_ALLOW_EXIT ) != 0;
        !          2336: 
        !          2337:        s_infinite_ammo_box.generic.type = MTYPE_SPINCONTROL;
        !          2338:        s_infinite_ammo_box.generic.x   = 0;
        !          2339:        s_infinite_ammo_box.generic.y   = y += 10;
        !          2340:        s_infinite_ammo_box.generic.name        = "infinite ammo";
        !          2341:        s_infinite_ammo_box.generic.callback = DMFlagCallback;
        !          2342:        s_infinite_ammo_box.itemnames = yes_no_names;
        !          2343:        s_infinite_ammo_box.curvalue = ( dmflags & DF_INFINITE_AMMO ) != 0;
        !          2344: 
        !          2345:        s_fixed_fov_box.generic.type = MTYPE_SPINCONTROL;
        !          2346:        s_fixed_fov_box.generic.x       = 0;
        !          2347:        s_fixed_fov_box.generic.y       = y += 10;
        !          2348:        s_fixed_fov_box.generic.name    = "fixed FOV";
        !          2349:        s_fixed_fov_box.generic.callback = DMFlagCallback;
        !          2350:        s_fixed_fov_box.itemnames = yes_no_names;
        !          2351:        s_fixed_fov_box.curvalue = ( dmflags & DF_FIXED_FOV ) != 0;
        !          2352: 
        !          2353:        s_quad_drop_box.generic.type = MTYPE_SPINCONTROL;
        !          2354:        s_quad_drop_box.generic.x       = 0;
        !          2355:        s_quad_drop_box.generic.y       = y += 10;
        !          2356:        s_quad_drop_box.generic.name    = "quad drop";
        !          2357:        s_quad_drop_box.generic.callback = DMFlagCallback;
        !          2358:        s_quad_drop_box.itemnames = yes_no_names;
        !          2359:        s_quad_drop_box.curvalue = ( dmflags & DF_QUAD_DROP ) != 0;
        !          2360: 
        !          2361:        s_friendlyfire_box.generic.type = MTYPE_SPINCONTROL;
        !          2362:        s_friendlyfire_box.generic.x    = 0;
        !          2363:        s_friendlyfire_box.generic.y    = y += 10;
        !          2364:        s_friendlyfire_box.generic.name = "friendly fire";
        !          2365:        s_friendlyfire_box.generic.callback = DMFlagCallback;
        !          2366:        s_friendlyfire_box.itemnames = yes_no_names;
        !          2367:        s_friendlyfire_box.curvalue = ( dmflags & DF_NO_FRIENDLY_FIRE ) == 0;
        !          2368: 
        !          2369:        Menu_AddItem( &s_dmoptions_menu, &s_falls_box );
        !          2370:        Menu_AddItem( &s_dmoptions_menu, &s_weapons_stay_box );
        !          2371:        Menu_AddItem( &s_dmoptions_menu, &s_instant_powerups_box );
        !          2372:        Menu_AddItem( &s_dmoptions_menu, &s_powerups_box );
        !          2373:        Menu_AddItem( &s_dmoptions_menu, &s_health_box );
        !          2374:        Menu_AddItem( &s_dmoptions_menu, &s_armor_box );
        !          2375:        Menu_AddItem( &s_dmoptions_menu, &s_spawn_farthest_box );
        !          2376:        Menu_AddItem( &s_dmoptions_menu, &s_samelevel_box );
        !          2377:        Menu_AddItem( &s_dmoptions_menu, &s_force_respawn_box );
        !          2378:        Menu_AddItem( &s_dmoptions_menu, &s_teamplay_box );
        !          2379:        Menu_AddItem( &s_dmoptions_menu, &s_allow_exit_box );
        !          2380:        Menu_AddItem( &s_dmoptions_menu, &s_infinite_ammo_box );
        !          2381:        Menu_AddItem( &s_dmoptions_menu, &s_fixed_fov_box );
        !          2382:        Menu_AddItem( &s_dmoptions_menu, &s_quad_drop_box );
        !          2383:        Menu_AddItem( &s_dmoptions_menu, &s_friendlyfire_box );
        !          2384: 
        !          2385:        Menu_Center( &s_dmoptions_menu );
        !          2386: 
        !          2387:        // set the original dmflags statusbar
        !          2388:        DMFlagCallback( 0 );
        !          2389:        Menu_SetStatusBar( &s_dmoptions_menu, dmoptions_statusbar );
        !          2390: }
        !          2391: 
        !          2392: void DMOptions_MenuDraw(void)
        !          2393: {
        !          2394:        Menu_Draw( &s_dmoptions_menu );
        !          2395: }
        !          2396: 
        !          2397: const char *DMOptions_MenuKey( int key )
        !          2398: {
        !          2399:        return Default_MenuKey( &s_dmoptions_menu, key );
        !          2400: }
        !          2401: 
        !          2402: void M_Menu_DMOptions_f (void)
        !          2403: {
        !          2404:        DMOptions_MenuInit();
        !          2405:        M_PushMenu( DMOptions_MenuDraw, DMOptions_MenuKey );
        !          2406: }
        !          2407: 
        !          2408: /*
        !          2409: =============================================================================
        !          2410: ADDRESS BOOK MENU
        !          2411: =============================================================================
        !          2412: */
        !          2413: #define NUM_ADDRESSBOOK_ENTRIES 9
        !          2414: static menuframework_s s_addressbook_menu;
        !          2415: static menufield_s             s_addressbook_fields[NUM_ADDRESSBOOK_ENTRIES];
        !          2416: void AddressBook_MenuInit( void )
        !          2417: {
        !          2418:        int i;
        !          2419:        s_addressbook_menu.x = viddef.width / 2 - 142;
        !          2420:        s_addressbook_menu.y = viddef.height / 2 - 58;
        !          2421:        s_addressbook_menu.nitems = 0;
        !          2422:        for ( i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++ )
        !          2423:        {
        !          2424:                cvar_t *adr;
        !          2425:                char buffer[20];
        !          2426: 
        !          2427:                Com_sprintf( buffer, sizeof( buffer ), "adr%d", i );
        !          2428: 
        !          2429:                adr = Cvar_Get( buffer, "", CVAR_ARCHIVE );
        !          2430:                s_addressbook_fields[i].generic.type = MTYPE_FIELD;
        !          2431:                s_addressbook_fields[i].generic.name = 0;
        !          2432:                s_addressbook_fields[i].generic.callback = 0;
        !          2433:                s_addressbook_fields[i].generic.x               = 0;
        !          2434:                s_addressbook_fields[i].generic.y               = i * 18 + 0;
        !          2435:                s_addressbook_fields[i].generic.localdata[0] = i;
        !          2436:                s_addressbook_fields[i].cursor                  = 0;
        !          2437:                s_addressbook_fields[i].length                  = 60;
        !          2438:                s_addressbook_fields[i].visible_length  = 30;
        !          2439: 
        !          2440:                strcpy( s_addressbook_fields[i].buffer, adr->string );
        !          2441:                Menu_AddItem( &s_addressbook_menu, &s_addressbook_fields[i] );
        !          2442:        }
        !          2443: }
        !          2444: const char *AddressBook_MenuKey( int key )
        !          2445: {
        !          2446:        if ( key == K_ESCAPE )
        !          2447:        {
        !          2448:                int index;
        !          2449:                char buffer[20];
        !          2450: 
        !          2451:                for ( index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++ )
        !          2452:                {
        !          2453:                        Com_sprintf( buffer, sizeof( buffer ), "adr%d", index );
        !          2454:                        Cvar_Set( buffer, s_addressbook_fields[index].buffer );
        !          2455:                }
        !          2456:        }
        !          2457:        return Default_MenuKey( &s_addressbook_menu, key );
        !          2458: }
        !          2459: void AddressBook_MenuDraw(void)
        !          2460: {
        !          2461:        M_Banner( "m_banner_addressbook" );
        !          2462:        Menu_Draw( &s_addressbook_menu );
        !          2463: }
        !          2464: void M_Menu_AddressBook_f(void)
        !          2465: {
        !          2466:        AddressBook_MenuInit();
        !          2467:        M_PushMenu( AddressBook_MenuDraw, AddressBook_MenuKey );
        !          2468: }
        !          2469: /*
        !          2470: =============================================================================
        !          2471: PLAYER CONFIG MENU
        !          2472: =============================================================================
        !          2473: */
        !          2474: static menuframework_s s_player_config_menu;
        !          2475: static menufield_s             s_player_name_field;
        !          2476: static menulist_s              s_player_model_box;
        !          2477: static menulist_s              s_player_skin_box;
        !          2478: static menulist_s              s_player_handedness_box;
        !          2479: static menuseparator_s s_player_skin_title;
        !          2480: static menuseparator_s s_player_model_title;
        !          2481: static menuseparator_s s_player_hand_title;
        !          2482: 
        !          2483: #define MAX_DISPLAYNAME 16
        !          2484: #define MAX_PLAYERMODELS 1024
        !          2485: 
        !          2486: typedef struct
        !          2487: {
        !          2488:        int             nskins;
        !          2489:        char    **skindisplaynames;
        !          2490:        char    displayname[MAX_DISPLAYNAME];
        !          2491:        char    directory[MAX_QPATH];
        !          2492: } playermodelinfo_s;
        !          2493: 
        !          2494: static playermodelinfo_s s_pmi[MAX_PLAYERMODELS];
        !          2495: static char *s_pmnames[MAX_PLAYERMODELS];
        !          2496: static int s_numplayermodels;
        !          2497: 
        !          2498: static void HandednessCallback( void *unused )
        !          2499: {
        !          2500:        Cvar_SetValue( "hand", s_player_handedness_box.curvalue );
        !          2501: }
        !          2502: 
        !          2503: static void ModelCallback( void *unused )
        !          2504: {
        !          2505:        s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
        !          2506:        s_player_skin_box.curvalue = 0;
        !          2507: }
        !          2508: 
        !          2509: static void FreeFileList( char **list, int n )
        !          2510: {
        !          2511:        int i;
        !          2512: 
        !          2513:        for ( i = 0; i < n; i++ )
        !          2514:        {
        !          2515:                if ( list[i] )
        !          2516:                {
        !          2517:                        free( list[i] );
        !          2518:                        list[i] = 0;
        !          2519:                }
        !          2520:        }
        !          2521:        free( list );
        !          2522: }
        !          2523: 
        !          2524: static qboolean IconOfSkinExists( char *skin, char **pcxfiles, int npcxfiles )
        !          2525: {
        !          2526:        int i;
        !          2527:        char scratch[1024];
        !          2528: 
        !          2529:        strcpy( scratch, skin );
        !          2530:        *strrchr( scratch, '.' ) = 0;
        !          2531:        strcat( scratch, "_i.pcx" );
        !          2532: 
        !          2533:        for ( i = 0; i < npcxfiles; i++ )
        !          2534:        {
        !          2535:                if ( strcmp( pcxfiles[i], scratch ) == 0 )
        !          2536:                        return true;
        !          2537:        }
        !          2538: 
        !          2539:        return false;
        !          2540: }
        !          2541: 
        !          2542: static qboolean PlayerConfig_ScanDirectories( void )
        !          2543: {
        !          2544:        char findname[1024];
        !          2545:        char scratch[1024];
        !          2546:        int ndirs = 0, npms = 0;
        !          2547:        char **dirnames;
        !          2548:        char *path = NULL;
        !          2549:        int i;
        !          2550: 
        !          2551:        extern char **FS_ListFiles( char *, int *, unsigned, unsigned );
        !          2552: 
        !          2553:        s_numplayermodels = 0;
        !          2554: 
        !          2555:        /*
        !          2556:        ** get a list of directories
        !          2557:        */
        !          2558:        do 
        !          2559:        {
        !          2560:                path = FS_NextPath( path );
        !          2561:                Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path );
        !          2562: 
        !          2563:                if ( ( dirnames = FS_ListFiles( findname, &ndirs, SFF_SUBDIR, 0 ) ) != 0 )
        !          2564:                        break;
        !          2565:        } while ( path );
        !          2566: 
        !          2567:        if ( !dirnames )
        !          2568:                return false;
        !          2569: 
        !          2570:        /*
        !          2571:        ** go through the subdirectories
        !          2572:        */
        !          2573:        npms = ndirs;
        !          2574:        if ( npms > MAX_PLAYERMODELS )
        !          2575:                npms = MAX_PLAYERMODELS;
        !          2576: 
        !          2577:        for ( i = 0; i < npms; i++ )
        !          2578:        {
        !          2579:                int k, s;
        !          2580:                char *a, *b, *c;
        !          2581:                char **pcxnames;
        !          2582:                char **skinnames;
        !          2583:                int npcxfiles;
        !          2584:                int nskins = 0;
        !          2585: 
        !          2586:                if ( dirnames[i] == 0 )
        !          2587:                        continue;
        !          2588: 
        !          2589:                // verify the existence of tris.md2
        !          2590:                strcpy( scratch, dirnames[i] );
        !          2591:                strcat( scratch, "/tris.md2" );
        !          2592:                if ( !Sys_FindFirst( scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM ) )
        !          2593:                {
        !          2594:                        free( dirnames[i] );
        !          2595:                        dirnames[i] = 0;
        !          2596:                        Sys_FindClose();
        !          2597:                        continue;
        !          2598:                }
        !          2599:                Sys_FindClose();
        !          2600: 
        !          2601:                // verify the existence of at least one pcx skin
        !          2602:                strcpy( scratch, dirnames[i] );
        !          2603:                strcat( scratch, "/*.pcx" );
        !          2604:                pcxnames = FS_ListFiles( scratch, &npcxfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM );
        !          2605: 
        !          2606:                if ( !pcxnames )
        !          2607:                {
        !          2608:                        free( dirnames[i] );
        !          2609:                        dirnames[i] = 0;
        !          2610:                        continue;
        !          2611:                }
        !          2612: 
        !          2613:                // count valid skins, which consist of a skin with a matching "_i" icon
        !          2614:                for ( k = 0; k < npcxfiles-1; k++ )
        !          2615:                {
        !          2616:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
        !          2617:                        {
        !          2618:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
        !          2619:                                {
        !          2620:                                        nskins++;
        !          2621:                                }
        !          2622:                        }
        !          2623:                }
        !          2624:                if ( !nskins )
        !          2625:                        continue;
        !          2626: 
        !          2627:                skinnames = malloc( sizeof( char * ) * ( nskins + 1 ) );
        !          2628:                memset( skinnames, 0, sizeof( char * ) * ( nskins + 1 ) );
        !          2629: 
        !          2630:                // copy the valid skins
        !          2631:                for ( s = 0, k = 0; k < npcxfiles-1; k++ )
        !          2632:                {
        !          2633:                        char *a, *b, *c;
        !          2634: 
        !          2635:                        if ( !strstr( pcxnames[k], "_i.pcx" ) )
        !          2636:                        {
        !          2637:                                if ( IconOfSkinExists( pcxnames[k], pcxnames, npcxfiles - 1 ) )
        !          2638:                                {
        !          2639:                                        a = strrchr( pcxnames[k], '/' );
        !          2640:                                        b = strrchr( pcxnames[k], '\\' );
        !          2641: 
        !          2642:                                        if ( a > b )
        !          2643:                                                c = a;
        !          2644:                                        else
        !          2645:                                                c = b;
        !          2646: 
        !          2647:                                        strcpy( scratch, c + 1 );
        !          2648: 
        !          2649:                                        if ( strrchr( scratch, '.' ) )
        !          2650:                                                *strrchr( scratch, '.' ) = 0;
        !          2651: 
        !          2652:                                        skinnames[s] = strdup( scratch );
        !          2653:                                        s++;
        !          2654:                                }
        !          2655:                        }
        !          2656:                }
        !          2657: 
        !          2658:                // at this point we have a valid player model
        !          2659:                s_pmi[s_numplayermodels].nskins = nskins;
        !          2660:                s_pmi[s_numplayermodels].skindisplaynames = skinnames;
        !          2661: 
        !          2662:                // make short name for the model
        !          2663:                a = strrchr( dirnames[i], '/' );
        !          2664:                b = strrchr( dirnames[i], '\\' );
        !          2665: 
        !          2666:                if ( a > b )
        !          2667:                        c = a;
        !          2668:                else
        !          2669:                        c = b;
        !          2670: 
        !          2671:                strncpy( s_pmi[s_numplayermodels].displayname, c + 1, MAX_DISPLAYNAME-1 );
        !          2672:                strcpy( s_pmi[s_numplayermodels].directory, c + 1 );
        !          2673: 
        !          2674:                FreeFileList( pcxnames, npcxfiles );
        !          2675: 
        !          2676:                s_numplayermodels++;
        !          2677:        }
        !          2678:        if ( dirnames )
        !          2679:                FreeFileList( dirnames, ndirs );
        !          2680: }
        !          2681: 
        !          2682: static int pmicmpfnc( const void *_a, const void *_b )
        !          2683: {
        !          2684:        const playermodelinfo_s *a = ( const playermodelinfo_s * ) _a;
        !          2685:        const playermodelinfo_s *b = ( const playermodelinfo_s * ) _b;
        !          2686: 
        !          2687:        /*
        !          2688:        ** sort by male, female, then alphabetical
        !          2689:        */
        !          2690:        if ( strcmp( a->directory, "male" ) == 0 )
        !          2691:                return -1;
        !          2692:        else if ( strcmp( b->directory, "male" ) == 0 )
        !          2693:                return 1;
        !          2694: 
        !          2695:        if ( strcmp( a->directory, "female" ) == 0 )
        !          2696:                return -1;
        !          2697:        else if ( strcmp( b->directory, "female" ) == 0 )
        !          2698:                return 1;
        !          2699: 
        !          2700:        return strcmp( a->directory, b->directory );
        !          2701: }
        !          2702: 
        !          2703: void PlayerConfig_MenuInit( void )
        !          2704: {
        !          2705:        extern cvar_t *name;
        !          2706:        extern cvar_t *team;
        !          2707:        extern cvar_t *skin;
        !          2708:        char currentdirectory[1024];
        !          2709:        char currentskin[1024];
        !          2710:        int i = 0;
        !          2711: 
        !          2712:        int currentdirectoryindex = 0;
        !          2713:        int currentskinindex = 0;
        !          2714: 
        !          2715:        cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
        !          2716: 
        !          2717:        static const char *handedness[] = { "right", "left", "center", 0 };
        !          2718: 
        !          2719:        PlayerConfig_ScanDirectories();
        !          2720: 
        !          2721:        if ( hand->value < 0 || hand->value > 2 )
        !          2722:                Cvar_SetValue( "hand", 0 );
        !          2723: 
        !          2724:        strcpy( currentdirectory, skin->string );
        !          2725: 
        !          2726:        if ( strchr( currentdirectory, '/' ) )
        !          2727:        {
        !          2728:                strcpy( currentskin, strchr( currentdirectory, '/' ) + 1 );
        !          2729:                *strchr( currentdirectory, '/' ) = 0;
        !          2730:        }
        !          2731:        else if ( strchr( currentdirectory, '\\' ) )
        !          2732:        {
        !          2733:                strcpy( currentskin, strchr( currentdirectory, '\\' ) + 1 );
        !          2734:                *strchr( currentdirectory, '\\' ) = 0;
        !          2735:        }
        !          2736:        else
        !          2737:        {
        !          2738:                strcpy( currentdirectory, "male" );
        !          2739:                strcpy( currentskin, "grunt" );
        !          2740:        }
        !          2741: 
        !          2742:        qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc );
        !          2743: 
        !          2744:        memset( s_pmnames, 0, sizeof( s_pmnames ) );
        !          2745:        for ( i = 0; i < s_numplayermodels; i++ )
        !          2746:        {
        !          2747:                s_pmnames[i] = s_pmi[i].displayname;
        !          2748:                if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 )
        !          2749:                {
        !          2750:                        int j;
        !          2751: 
        !          2752:                        currentdirectoryindex = i;
        !          2753: 
        !          2754:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
        !          2755:                        {
        !          2756:                                if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 )
        !          2757:                                {
        !          2758:                                        currentskinindex = j;
        !          2759:                                        break;
        !          2760:                                }
        !          2761:                        }
        !          2762:                }
        !          2763:        }
        !          2764: 
        !          2765:        s_player_config_menu.x = viddef.width / 2 - 95; 
        !          2766:        s_player_config_menu.y = viddef.height / 2 - 97;
        !          2767:        s_player_config_menu.nitems = 0;
        !          2768: 
        !          2769:        s_player_name_field.generic.type = MTYPE_FIELD;
        !          2770:        s_player_name_field.generic.name = "name";
        !          2771:        s_player_name_field.generic.callback = 0;
        !          2772:        s_player_name_field.generic.x           = 0;
        !          2773:        s_player_name_field.generic.y           = 0;
        !          2774:        s_player_name_field.length      = 20;
        !          2775:        s_player_name_field.visible_length = 20;
        !          2776:        strcpy( s_player_name_field.buffer, name->string );
        !          2777:        s_player_name_field.cursor = strlen( name->string );
        !          2778: 
        !          2779:        s_player_model_title.generic.type = MTYPE_SEPARATOR;
        !          2780:        s_player_model_title.generic.name = "model";
        !          2781:        s_player_model_title.generic.x    = -8;
        !          2782:        s_player_model_title.generic.y   = 60;
        !          2783: 
        !          2784:        s_player_model_box.generic.type = MTYPE_SPINCONTROL;
        !          2785:        s_player_model_box.generic.x    = -56;
        !          2786:        s_player_model_box.generic.y    = 70;
        !          2787:        s_player_model_box.generic.callback = ModelCallback;
        !          2788:        s_player_model_box.generic.cursor_offset = -48;
        !          2789:        s_player_model_box.curvalue = currentdirectoryindex;
        !          2790:        s_player_model_box.itemnames = s_pmnames;
        !          2791: 
        !          2792:        s_player_skin_title.generic.type = MTYPE_SEPARATOR;
        !          2793:        s_player_skin_title.generic.name = "skin";
        !          2794:        s_player_skin_title.generic.x    = -16;
        !          2795:        s_player_skin_title.generic.y    = 84;
        !          2796: 
        !          2797:        s_player_skin_box.generic.type = MTYPE_SPINCONTROL;
        !          2798:        s_player_skin_box.generic.x     = -56;
        !          2799:        s_player_skin_box.generic.y     = 94;
        !          2800:        s_player_skin_box.generic.name  = 0;
        !          2801:        s_player_skin_box.generic.callback = 0;
        !          2802:        s_player_skin_box.generic.cursor_offset = -48;
        !          2803:        s_player_skin_box.curvalue = currentskinindex;
        !          2804:        s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
        !          2805: 
        !          2806:        s_player_hand_title.generic.type = MTYPE_SEPARATOR;
        !          2807:        s_player_hand_title.generic.name = "handedness";
        !          2808:        s_player_hand_title.generic.x    = 32;
        !          2809:        s_player_hand_title.generic.y    = 108;
        !          2810: 
        !          2811:        s_player_handedness_box.generic.type = MTYPE_SPINCONTROL;
        !          2812:        s_player_handedness_box.generic.x       = -56;
        !          2813:        s_player_handedness_box.generic.y       = 118;
        !          2814:        s_player_handedness_box.generic.name    = 0;
        !          2815:        s_player_handedness_box.generic.cursor_offset = -48;
        !          2816:        s_player_handedness_box.generic.callback = HandednessCallback;
        !          2817:        s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" );
        !          2818:        s_player_handedness_box.itemnames = handedness;
        !          2819: 
        !          2820:        Menu_AddItem( &s_player_config_menu, &s_player_name_field );
        !          2821:        Menu_AddItem( &s_player_config_menu, &s_player_model_title );
        !          2822:        Menu_AddItem( &s_player_config_menu, &s_player_model_box );
        !          2823:        if ( s_player_skin_box.itemnames )
        !          2824:        {
        !          2825:                Menu_AddItem( &s_player_config_menu, &s_player_skin_title );
        !          2826:                Menu_AddItem( &s_player_config_menu, &s_player_skin_box );
        !          2827:        }
        !          2828:        Menu_AddItem( &s_player_config_menu, &s_player_hand_title );
        !          2829:        Menu_AddItem( &s_player_config_menu, &s_player_handedness_box );
        !          2830: }
        !          2831: 
        !          2832: void PlayerConfig_MenuDraw( void )
        !          2833: {
        !          2834:        extern float CalcFov( float fov_x, float w, float h );
        !          2835:        refdef_t refdef;
        !          2836:        char scratch[MAX_QPATH];
        !          2837: 
        !          2838:        memset( &refdef, 0, sizeof( refdef ) );
        !          2839: 
        !          2840:        refdef.x = viddef.width / 2;
        !          2841:        refdef.y = viddef.height / 2 - 72;
        !          2842:        refdef.width = 144;
        !          2843:        refdef.height = 168;
        !          2844:        refdef.fov_x = 40;
        !          2845:        refdef.fov_y = CalcFov( refdef.fov_x, refdef.width, refdef.height );
        !          2846:        refdef.time = cls.realtime*0.001;
        !          2847: 
        !          2848:        if ( s_pmi[s_player_model_box.curvalue].skindisplaynames )
        !          2849:        {
        !          2850:                static int yaw;
        !          2851:                int maxframe = 29;
        !          2852:                entity_t entity;
        !          2853: 
        !          2854:                memset( &entity, 0, sizeof( entity ) );
        !          2855: 
        !          2856:                Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory );
        !          2857:                entity.model = re.RegisterModel( scratch );
        !          2858:                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] );
        !          2859:                entity.skin = re.RegisterSkin( scratch );
        !          2860:                entity.flags = RF_FULLBRIGHT;
        !          2861:                entity.origin[0] = 80;
        !          2862:                entity.origin[1] = 0;
        !          2863:                entity.origin[2] = 0;
        !          2864:                VectorCopy( entity.origin, entity.oldorigin );
        !          2865:                entity.frame = 0;
        !          2866:                entity.oldframe = 0;
        !          2867:                entity.backlerp = 0.0;
        !          2868:                entity.angles[1] = yaw++;
        !          2869:                if ( ++yaw > 360 )
        !          2870:                        yaw -= 360;
        !          2871: 
        !          2872:                refdef.areabits = 0;
        !          2873:                refdef.num_entities = 1;
        !          2874:                refdef.entities = &entity;
        !          2875:                refdef.lightstyles = 0;
        !          2876:                refdef.rdflags = RDF_NOWORLDMODEL;
        !          2877: 
        !          2878:                Menu_Draw( &s_player_config_menu );
        !          2879: 
        !          2880:                M_DrawTextBox( ( refdef.x ) * ( 320.0F / viddef.width ) - 8, ( viddef.height / 2 ) * ( 240.0F / viddef.height) - 77, refdef.width / 8, refdef.height / 8 );
        !          2881:                refdef.height += 4;
        !          2882: 
        !          2883:                re.RenderFrame( &refdef );
        !          2884: 
        !          2885:                Com_sprintf( scratch, sizeof( scratch ), "/players/%s/%s_i.pcx", 
        !          2886:                        s_pmi[s_player_model_box.curvalue].directory,
        !          2887:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
        !          2888:                re.DrawPic( s_player_config_menu.x - 40, refdef.y, scratch );
        !          2889:        }
        !          2890: }
        !          2891: const char *PlayerConfig_MenuKey (int key)
        !          2892: {
        !          2893:        int i;
        !          2894: 
        !          2895:        if ( key == K_ESCAPE )
        !          2896:        {
        !          2897:                char scratch[1024];
        !          2898: 
        !          2899:                Cvar_Set( "name", s_player_name_field.buffer );
        !          2900: 
        !          2901:                Com_sprintf( scratch, sizeof( scratch ), "%s/%s", 
        !          2902:                        s_pmi[s_player_model_box.curvalue].directory, 
        !          2903:                        s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] );
        !          2904: 
        !          2905:                Cvar_Set( "skin", scratch );
        !          2906: 
        !          2907:                for ( i = 0; i < s_numplayermodels; i++ )
        !          2908:                {
        !          2909:                        int j;
        !          2910: 
        !          2911:                        for ( j = 0; j < s_pmi[i].nskins; j++ )
        !          2912:                        {
        !          2913:                                if ( s_pmi[i].skindisplaynames[j] )
        !          2914:                                        free( s_pmi[i].skindisplaynames[j] );
        !          2915:                                s_pmi[i].skindisplaynames[j] = 0;
        !          2916:                        }
        !          2917:                        free( s_pmi[i].skindisplaynames );
        !          2918:                        s_pmi[i].skindisplaynames = 0;
        !          2919:                        s_pmi[i].nskins = 0;
        !          2920:                }
        !          2921:        }
        !          2922:        return Default_MenuKey( &s_player_config_menu, key );
        !          2923: }
        !          2924: void M_Menu_PlayerConfig_f (void)
        !          2925: {
        !          2926:        PlayerConfig_MenuInit();
        !          2927:        M_PushMenu( PlayerConfig_MenuDraw, PlayerConfig_MenuKey );
        !          2928: }
        !          2929: /*
        !          2930: =======================================================================
        !          2931: 
        !          2932: GALLERY MENU
        !          2933: 
        !          2934: =======================================================================
        !          2935: */
        !          2936: #if 0
        !          2937: void M_Menu_Gallery_f( void )
        !          2938: {
        !          2939:        extern void Gallery_MenuDraw( void );
        !          2940:        extern const char *Gallery_MenuKey( int key );
        !          2941:        M_PushMenu( Gallery_MenuDraw, Gallery_MenuKey );
        !          2942: }
        !          2943: #endif
        !          2944: /*
        !          2945: =======================================================================
        !          2946: QUIT MENU
        !          2947: =======================================================================
        !          2948: */
        !          2949: const char *M_Quit_Key (int key)
        !          2950: {
        !          2951:        switch (key)
        !          2952:        {
        !          2953:        case K_ESCAPE:
        !          2954:        case 'n':
        !          2955:        case 'N':
        !          2956:                M_PopMenu ();
        !          2957:                break;
        !          2958:        case 'Y':
        !          2959:        case 'y':
        !          2960:                cls.key_dest = key_console;
        !          2961:                CL_Quit_f ();
        !          2962:                break;
        !          2963:        default:
        !          2964:                break;
        !          2965:        }
        !          2966:        return NULL;
        !          2967: }
        !          2968: void M_Quit_Draw (void)
        !          2969: {
        !          2970:        int             w, h;
        !          2971:        re.DrawGetPicSize (&w, &h, "quit");
        !          2972:        re.DrawPic ( (viddef.width-w)/2, (viddef.height-h)/2, "quit");
        !          2973: }
        !          2974: void M_Menu_Quit_f (void)
        !          2975: {
        !          2976:        M_PushMenu (M_Quit_Draw, M_Quit_Key);
        !          2977: }
        !          2978: //=============================================================================
        !          2979: /* Menu Subsystem */
        !          2980: /*
        !          2981: =================
        !          2982: M_Init
        !          2983: =================
        !          2984: */
        !          2985: void M_Init (void)
        !          2986: {
        !          2987:        Cmd_AddCommand ("menu_main", M_Menu_Main_f);
        !          2988:        Cmd_AddCommand ("menu_game", M_Menu_Game_f);
        !          2989:                Cmd_AddCommand ("menu_loadgame", M_Menu_LoadGame_f);
        !          2990:                Cmd_AddCommand ("menu_savegame", M_Menu_SaveGame_f);
        !          2991:                Cmd_AddCommand ("menu_joinserver", M_Menu_JoinServer_f);
        !          2992:                        Cmd_AddCommand ("menu_addressbook", M_Menu_AddressBook_f);
        !          2993:                Cmd_AddCommand ("menu_startserver", M_Menu_StartServer_f);
        !          2994:                        Cmd_AddCommand ("menu_dmoptions", M_Menu_DMOptions_f);
        !          2995:                Cmd_AddCommand ("menu_playerconfig", M_Menu_PlayerConfig_f);
        !          2996:                Cmd_AddCommand ("menu_credits", M_Menu_Credits_f );
        !          2997:        Cmd_AddCommand ("menu_multiplayer", M_Menu_Multiplayer_f );
        !          2998:        Cmd_AddCommand ("menu_video", M_Menu_Video_f);
        !          2999:        Cmd_AddCommand ("menu_options", M_Menu_Options_f);
        !          3000:                Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
        !          3001:        Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
        !          3002: }
        !          3003: /*
        !          3004: =================
        !          3005: M_Draw
        !          3006: =================
        !          3007: */
        !          3008: void M_Draw (void)
        !          3009: {
        !          3010:        if (cls.key_dest != key_menu)
        !          3011:                return;
        !          3012:        // repaint everything next frame
        !          3013:        SCR_DirtyScreen ();
        !          3014:        // dim everything behind it down
        !          3015:        if (cl.cinematictime > 0)
        !          3016:                re.DrawFill (0,0,viddef.width, viddef.height, 0);
        !          3017:        else
        !          3018:                re.DrawFadeScreen ();
        !          3019:        m_drawfunc ();
        !          3020:        // delay playing the enter sound until after the
        !          3021:        // menu has been drawn, to avoid delay while
        !          3022:        // caching images
        !          3023:        if (m_entersound)
        !          3024:        {
        !          3025:                S_StartLocalSound( menu_in_sound );
        !          3026:                m_entersound = false;
        !          3027:        }
        !          3028: }
        !          3029: /*
        !          3030: =================
        !          3031: M_Keydown
        !          3032: =================
        !          3033: */
        !          3034: void M_Keydown (int key)
        !          3035: {
        !          3036:        const char *s;
        !          3037:        if (m_keyfunc)
        !          3038:                if ( ( s = m_keyfunc( key ) ) != 0 )
        !          3039:                        S_StartLocalSound( ( char * ) s );
        !          3040: }

unix.superglobalmegacorp.com

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