home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  25.0 KB  |  1,327 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "quakedef.h"
  21. #include "winquake.h"
  22.  
  23. void (*vid_menudrawfn)(void);
  24. void (*vid_menukeyfn)(int key);
  25.  
  26. enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
  27.  
  28. void M_Menu_Main_f (void);
  29.     void M_Menu_SinglePlayer_f (void);
  30.         void M_Menu_Load_f (void);
  31.         void M_Menu_Save_f (void);
  32.     void M_Menu_MultiPlayer_f (void);
  33.         void M_Menu_Setup_f (void);
  34.         void M_Menu_Net_f (void);
  35.     void M_Menu_Options_f (void);
  36.         void M_Menu_Keys_f (void);
  37.         void M_Menu_Video_f (void);
  38.     void M_Menu_Help_f (void);
  39.     void M_Menu_Quit_f (void);
  40. void M_Menu_SerialConfig_f (void);
  41.     void M_Menu_ModemConfig_f (void);
  42. void M_Menu_LanConfig_f (void);
  43. void M_Menu_GameOptions_f (void);
  44. void M_Menu_Search_f (void);
  45. void M_Menu_ServerList_f (void);
  46.  
  47. void M_Main_Draw (void);
  48.     void M_SinglePlayer_Draw (void);
  49.         void M_Load_Draw (void);
  50.         void M_Save_Draw (void);
  51.     void M_MultiPlayer_Draw (void);
  52.         void M_Setup_Draw (void);
  53.         void M_Net_Draw (void);
  54.     void M_Options_Draw (void);
  55.         void M_Keys_Draw (void);
  56.         void M_Video_Draw (void);
  57.     void M_Help_Draw (void);
  58.     void M_Quit_Draw (void);
  59. void M_SerialConfig_Draw (void);
  60.     void M_ModemConfig_Draw (void);
  61. void M_LanConfig_Draw (void);
  62. void M_GameOptions_Draw (void);
  63. void M_Search_Draw (void);
  64. void M_ServerList_Draw (void);
  65.  
  66. void M_Main_Key (int key);
  67.     void M_SinglePlayer_Key (int key);
  68.         void M_Load_Key (int key);
  69.         void M_Save_Key (int key);
  70.     void M_MultiPlayer_Key (int key);
  71.         void M_Setup_Key (int key);
  72.         void M_Net_Key (int key);
  73.     void M_Options_Key (int key);
  74.         void M_Keys_Key (int key);
  75.         void M_Video_Key (int key);
  76.     void M_Help_Key (int key);
  77.     void M_Quit_Key (int key);
  78. void M_SerialConfig_Key (int key);
  79.     void M_ModemConfig_Key (int key);
  80. void M_LanConfig_Key (int key);
  81. void M_GameOptions_Key (int key);
  82. void M_Search_Key (int key);
  83. void M_ServerList_Key (int key);
  84.  
  85. qboolean    m_entersound;        // play after drawing a frame, so caching
  86.                                 // won't disrupt the sound
  87. qboolean    m_recursiveDraw;
  88.  
  89. int            m_return_state;
  90. qboolean    m_return_onerror;
  91. char        m_return_reason [32];
  92.  
  93. #define StartingGame    (m_multiplayer_cursor == 1)
  94. #define JoiningGame        (m_multiplayer_cursor == 0)
  95. #define SerialConfig    (m_net_cursor == 0)
  96. #define DirectConfig    (m_net_cursor == 1)
  97. #define    IPXConfig        (m_net_cursor == 2)
  98. #define    TCPIPConfig        (m_net_cursor == 3)
  99.  
  100. void M_ConfigureNetSubsystem(void);
  101.  
  102. //=============================================================================
  103. /* Support Routines */
  104.  
  105. /*
  106. ================
  107. M_DrawCharacter
  108.  
  109. Draws one solid graphics character
  110. ================
  111. */
  112. void M_DrawCharacter (int cx, int line, int num)
  113. {
  114.     Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
  115. }
  116.  
  117. void M_Print (int cx, int cy, char *str)
  118. {
  119.     while (*str)
  120.     {
  121.         M_DrawCharacter (cx, cy, (*str)+128);
  122.         str++;
  123.         cx += 8;
  124.     }
  125. }
  126.  
  127. void M_PrintWhite (int cx, int cy, char *str)
  128. {
  129.     while (*str)
  130.     {
  131.         M_DrawCharacter (cx, cy, *str);
  132.         str++;
  133.         cx += 8;
  134.     }
  135. }
  136.  
  137. void M_DrawTransPic (int x, int y, qpic_t *pic)
  138. {
  139.     Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
  140. }
  141.  
  142. void M_DrawPic (int x, int y, qpic_t *pic)
  143. {
  144.     Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
  145. }
  146.  
  147. byte identityTable[256];
  148. byte translationTable[256];
  149.  
  150. void M_BuildTranslationTable(int top, int bottom)
  151. {
  152.     int        j;
  153.     byte    *dest, *source;
  154.  
  155.     for (j = 0; j < 256; j++)
  156.         identityTable[j] = j;
  157.     dest = translationTable;
  158.     source = identityTable;
  159.     memcpy (dest, source, 256);
  160.  
  161.     if (top < 128)    // the artists made some backwards ranges.  sigh.
  162.         memcpy (dest + TOP_RANGE, source + top, 16);
  163.     else
  164.         for (j=0 ; j<16 ; j++)
  165.             dest[TOP_RANGE+j] = source[top+15-j];
  166.  
  167.     if (bottom < 128)
  168.         memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
  169.     else
  170.         for (j=0 ; j<16 ; j++)
  171.             dest[BOTTOM_RANGE+j] = source[bottom+15-j];        
  172. }
  173.  
  174.  
  175. void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
  176. {
  177.     Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
  178. }
  179.  
  180.  
  181. void M_DrawTextBox (int x, int y, int width, int lines)
  182. {
  183.     qpic_t    *p;
  184.     int        cx, cy;
  185.     int        n;
  186.  
  187.     // draw left side
  188.     cx = x;
  189.     cy = y;
  190.     p = Draw_CachePic ("gfx/box_tl.lmp");
  191.     M_DrawTransPic (cx, cy, p);
  192.     p = Draw_CachePic ("gfx/box_ml.lmp");
  193.     for (n = 0; n < lines; n++)
  194.     {
  195.         cy += 8;
  196.         M_DrawTransPic (cx, cy, p);
  197.     }
  198.     p = Draw_CachePic ("gfx/box_bl.lmp");
  199.     M_DrawTransPic (cx, cy+8, p);
  200.  
  201.     // draw middle
  202.     cx += 8;
  203.     while (width > 0)
  204.     {
  205.         cy = y;
  206.         p = Draw_CachePic ("gfx/box_tm.lmp");
  207.         M_DrawTransPic (cx, cy, p);
  208.         p = Draw_CachePic ("gfx/box_mm.lmp");
  209.         for (n = 0; n < lines; n++)
  210.         {
  211.             cy += 8;
  212.             if (n == 1)
  213.                 p = Draw_CachePic ("gfx/box_mm2.lmp");
  214.             M_DrawTransPic (cx, cy, p);
  215.         }
  216.         p = Draw_CachePic ("gfx/box_bm.lmp");
  217.         M_DrawTransPic (cx, cy+8, p);
  218.         width -= 2;
  219.         cx += 16;
  220.     }
  221.  
  222.     // draw right side
  223.     cy = y;
  224.     p = Draw_CachePic ("gfx/box_tr.lmp");
  225.     M_DrawTransPic (cx, cy, p);
  226.     p = Draw_CachePic ("gfx/box_mr.lmp");
  227.     for (n = 0; n < lines; n++)
  228.     {
  229.         cy += 8;
  230.         M_DrawTransPic (cx, cy, p);
  231.     }
  232.     p = Draw_CachePic ("gfx/box_br.lmp");
  233.     M_DrawTransPic (cx, cy+8, p);
  234. }
  235.  
  236. //=============================================================================
  237.  
  238. int m_save_demonum;
  239.         
  240. /*
  241. ================
  242. M_ToggleMenu_f
  243. ================
  244. */
  245. void M_ToggleMenu_f (void)
  246. {
  247.     m_entersound = true;
  248.  
  249.     if (key_dest == key_menu)
  250.     {
  251.         if (m_state != m_main)
  252.         {
  253.             M_Menu_Main_f ();
  254.             return;
  255.         }
  256.         key_dest = key_game;
  257.         m_state = m_none;
  258.         return;
  259.     }
  260.     if (key_dest == key_console)
  261.     {
  262.         Con_ToggleConsole_f ();
  263.     }
  264.     else
  265.     {
  266.         M_Menu_Main_f ();
  267.     }
  268. }
  269.  
  270.         
  271. //=============================================================================
  272. /* MAIN MENU */
  273.  
  274. int    m_main_cursor;
  275. #define    MAIN_ITEMS    5
  276.  
  277.  
  278. void M_Menu_Main_f (void)
  279. {
  280.     if (key_dest != key_menu)
  281.     {
  282.         m_save_demonum = cls.demonum;
  283.         cls.demonum = -1;
  284.     }
  285.     key_dest = key_menu;
  286.     m_state = m_main;
  287.     m_entersound = true;
  288. }
  289.                 
  290.  
  291. void M_Main_Draw (void)
  292. {
  293.     int        f;
  294.     qpic_t    *p;
  295.  
  296.     M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  297.     p = Draw_CachePic ("gfx/ttl_main.lmp");
  298.     M_DrawPic ( (320-p->width)/2, 4, p);
  299.     M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
  300.  
  301.     f = (int)(realtime * 10)%6;
  302.     
  303.     M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
  304. }
  305.  
  306.  
  307. void M_Main_Key (int key)
  308. {
  309.     switch (key)
  310.     {
  311.     case K_ESCAPE:
  312.         key_dest = key_game;
  313.         m_state = m_none;
  314.         cls.demonum = m_save_demonum;
  315.         if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected)
  316.             CL_NextDemo ();
  317.         break;
  318.         
  319.     case K_DOWNARROW:
  320.         S_LocalSound ("misc/menu1.wav");
  321.         if (++m_main_cursor >= MAIN_ITEMS)
  322.             m_main_cursor = 0;
  323.         break;
  324.  
  325.     case K_UPARROW:
  326.         S_LocalSound ("misc/menu1.wav");
  327.         if (--m_main_cursor < 0)
  328.             m_main_cursor = MAIN_ITEMS - 1;
  329.         break;
  330.  
  331.     case K_ENTER:
  332.         m_entersound = true;
  333.  
  334.         switch (m_main_cursor)
  335.         {
  336.         case 0:
  337.             M_Menu_SinglePlayer_f ();
  338.             break;
  339.  
  340.         case 1:
  341.             M_Menu_MultiPlayer_f ();
  342.             break;
  343.  
  344.         case 2:
  345.             M_Menu_Options_f ();
  346.             break;
  347.  
  348.         case 3:
  349.             M_Menu_Help_f ();
  350.             break;
  351.  
  352.         case 4:
  353.             M_Menu_Quit_f ();
  354.             break;
  355.         }
  356.     }
  357. }
  358.  
  359.  
  360. //=============================================================================
  361. /* OPTIONS MENU */
  362.  
  363. #define    OPTIONS_ITEMS    16
  364.  
  365. #define    SLIDER_RANGE    10
  366.  
  367. int        options_cursor;
  368.  
  369. void M_Menu_Options_f (void)
  370. {
  371.     key_dest = key_menu;
  372.     m_state = m_options;
  373.     m_entersound = true;
  374. }
  375.  
  376.  
  377. void M_AdjustSliders (int dir)
  378. {
  379.     S_LocalSound ("misc/menu3.wav");
  380.  
  381.     switch (options_cursor)
  382.     {
  383.     case 3:    // screen size
  384.         scr_viewsize.value += dir * 10;
  385.         if (scr_viewsize.value < 30)
  386.             scr_viewsize.value = 30;
  387.         if (scr_viewsize.value > 120)
  388.             scr_viewsize.value = 120;
  389.         Cvar_SetValue ("viewsize", scr_viewsize.value);
  390.         break;
  391.     case 4:    // gamma
  392.         v_gamma.value -= dir * 0.05;
  393.         if (v_gamma.value < 0.5)
  394.             v_gamma.value = 0.5;
  395.         if (v_gamma.value > 1)
  396.             v_gamma.value = 1;
  397.         Cvar_SetValue ("gamma", v_gamma.value);
  398.         break;
  399.     case 5:    // mouse speed
  400.         sensitivity.value += dir * 0.5;
  401.         if (sensitivity.value < 1)
  402.             sensitivity.value = 1;
  403.         if (sensitivity.value > 11)
  404.             sensitivity.value = 11;
  405.         Cvar_SetValue ("sensitivity", sensitivity.value);
  406.         break;
  407.     case 6:    // music volume
  408. #ifdef _WIN32
  409.         bgmvolume.value += dir * 1.0;
  410. #else
  411.         bgmvolume.value += dir * 0.1;
  412. #endif
  413.         if (bgmvolume.value < 0)
  414.             bgmvolume.value = 0;
  415.         if (bgmvolume.value > 1)
  416.             bgmvolume.value = 1;
  417.         Cvar_SetValue ("bgmvolume", bgmvolume.value);
  418.         break;
  419.     case 7:    // sfx volume
  420.         volume.value += dir * 0.1;
  421.         if (volume.value < 0)
  422.             volume.value = 0;
  423.         if (volume.value > 1)
  424.             volume.value = 1;
  425.         Cvar_SetValue ("volume", volume.value);
  426.         break;
  427.         
  428.     case 8:    // allways run
  429.         if (cl_forwardspeed.value > 200)
  430.         {
  431.             Cvar_SetValue ("cl_forwardspeed", 200);
  432.             Cvar_SetValue ("cl_backspeed", 200);
  433.         }
  434.         else
  435.         {
  436.             Cvar_SetValue ("cl_forwardspeed", 400);
  437.             Cvar_SetValue ("cl_backspeed", 400);
  438.         }
  439.         break;
  440.     
  441.     case 9:    // invert mouse
  442.         Cvar_SetValue ("m_pitch", -m_pitch.value);
  443.         break;
  444.     
  445.     case 10:    // lookspring
  446.         Cvar_SetValue ("lookspring", !lookspring.value);
  447.         break;
  448.     
  449.     case 11:    // lookstrafe
  450.         Cvar_SetValue ("lookstrafe", !lookstrafe.value);
  451.         break;
  452.  
  453.     case 12:
  454.         Cvar_SetValue ("cl_sbar", !cl_sbar.value);
  455.         break;
  456.  
  457.     case 13:
  458.         Cvar_SetValue ("cl_hudswap", !cl_hudswap.value);
  459.  
  460.     case 15:    // _windowed_mouse
  461.         Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
  462.         break;
  463.     }
  464. }
  465.  
  466.  
  467. void M_DrawSlider (int x, int y, float range)
  468. {
  469.     int    i;
  470.  
  471.     if (range < 0)
  472.         range = 0;
  473.     if (range > 1)
  474.         range = 1;
  475.     M_DrawCharacter (x-8, y, 128);
  476.     for (i=0 ; i<SLIDER_RANGE ; i++)
  477.         M_DrawCharacter (x + i*8, y, 129);
  478.     M_DrawCharacter (x+i*8, y, 130);
  479.     M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
  480. }
  481.  
  482. void M_DrawCheckbox (int x, int y, int on)
  483. {
  484. #if 0
  485.     if (on)
  486.         M_DrawCharacter (x, y, 131);
  487.     else
  488.         M_DrawCharacter (x, y, 129);
  489. #endif
  490.     if (on)
  491.         M_Print (x, y, "on");
  492.     else
  493.         M_Print (x, y, "off");
  494. }
  495.  
  496. void M_Options_Draw (void)
  497. {
  498.     float        r;
  499.     qpic_t    *p;
  500.     
  501.     M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  502.     p = Draw_CachePic ("gfx/p_option.lmp");
  503.     M_DrawPic ( (320-p->width)/2, 4, p);
  504.     
  505.     M_Print (16, 32, "    Customize controls");
  506.     M_Print (16, 40, "         Go to console");
  507.     M_Print (16, 48, "     Reset to defaults");
  508.  
  509.     M_Print (16, 56, "           Screen size");
  510.     r = (scr_viewsize.value - 30) / (120 - 30);
  511.     M_DrawSlider (220, 56, r);
  512.  
  513.     M_Print (16, 64, "            Brightness");
  514.     r = (1.0 - v_gamma.value) / 0.5;
  515.     M_DrawSlider (220, 64, r);
  516.  
  517.     M_Print (16, 72, "           Mouse Speed");
  518.     r = (sensitivity.value - 1)/10;
  519.     M_DrawSlider (220, 72, r);
  520.  
  521.     M_Print (16, 80, "       CD Music Volume");
  522.     r = bgmvolume.value;
  523.     M_DrawSlider (220, 80, r);
  524.  
  525.     M_Print (16, 88, "          Sound Volume");
  526.     r = volume.value;
  527.     M_DrawSlider (220, 88, r);
  528.  
  529.     M_Print (16, 96,  "            Always Run");
  530.     M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
  531.  
  532.     M_Print (16, 104, "          Invert Mouse");
  533.     M_DrawCheckbox (220, 104, m_pitch.value < 0);
  534.  
  535.     M_Print (16, 112, "            Lookspring");
  536.     M_DrawCheckbox (220, 112, lookspring.value);
  537.  
  538.     M_Print (16, 120, "            Lookstrafe");
  539.     M_DrawCheckbox (220, 120, lookstrafe.value);
  540.  
  541.     M_Print (16, 128, "    Use old status bar");
  542.     M_DrawCheckbox (220, 128, cl_sbar.value);
  543.  
  544.     M_Print (16, 136, "      HUD on left side");
  545.     M_DrawCheckbox (220, 136, cl_hudswap.value);
  546.  
  547.     if (vid_menudrawfn)
  548.         M_Print (16, 144, "         Video Options");
  549.  
  550. #ifdef _WIN32
  551.     if (modestate == MS_WINDOWED)
  552.     {
  553. #endif
  554.         M_Print (16, 152, "             Use Mouse");
  555.         M_DrawCheckbox (220, 152, _windowed_mouse.value);
  556. #ifdef _WIN32
  557.     }
  558. #endif
  559.  
  560. // cursor
  561.     M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
  562. }
  563.  
  564.  
  565. void M_Options_Key (int k)
  566. {
  567.     switch (k)
  568.     {
  569.     case K_ESCAPE:
  570.         M_Menu_Main_f ();
  571.         break;
  572.         
  573.     case K_ENTER:
  574.         m_entersound = true;
  575.         switch (options_cursor)
  576.         {
  577.         case 0:
  578.             M_Menu_Keys_f ();
  579.             break;
  580.         case 1:
  581.             m_state = m_none;
  582.             Con_ToggleConsole_f ();
  583.             break;
  584.         case 2:
  585.             Cbuf_AddText ("exec default.cfg\n");
  586.             break;
  587.         case 14:
  588.             M_Menu_Video_f ();
  589.             break;
  590.         default:
  591.             M_AdjustSliders (1);
  592.             break;
  593.         }
  594.         return;
  595.     
  596.     case K_UPARROW:
  597.         S_LocalSound ("misc/menu1.wav");
  598.         options_cursor--;
  599.         if (options_cursor < 0)
  600.             options_cursor = OPTIONS_ITEMS-1;
  601.         break;
  602.  
  603.     case K_DOWNARROW:
  604.         S_LocalSound ("misc/menu1.wav");
  605.         options_cursor++;
  606.         if (options_cursor >= OPTIONS_ITEMS)
  607.             options_cursor = 0;
  608.         break;    
  609.  
  610.     case K_LEFTARROW:
  611.         M_AdjustSliders (-1);
  612.         break;
  613.  
  614.     case K_RIGHTARROW:
  615.         M_AdjustSliders (1);
  616.         break;
  617.     }
  618.  
  619.     if (options_cursor == 14 && vid_menudrawfn == NULL)
  620.     {
  621.         if (k == K_UPARROW)
  622.             options_cursor = 13;
  623.         else
  624.             options_cursor = 0;
  625.     }
  626.  
  627.     if ((options_cursor == 15) 
  628. #ifdef _WIN32
  629.     && (modestate != MS_WINDOWED)
  630. #endif
  631.     )
  632.     {
  633.         if (k == K_UPARROW)
  634.             options_cursor = 14;
  635.         else
  636.             options_cursor = 0;
  637.     }
  638. }
  639.  
  640.  
  641. //=============================================================================
  642. /* KEYS MENU */
  643.  
  644. char *bindnames[][2] =
  645. {
  646. {"+attack",         "attack"},
  647. {"impulse 10",         "change weapon"},
  648. {"+jump",             "jump / swim up"},
  649. {"+forward",         "walk forward"},
  650. {"+back",             "backpedal"},
  651. {"+left",             "turn left"},
  652. {"+right",             "turn right"},
  653. {"+speed",             "run"},
  654. {"+moveleft",         "step left"},
  655. {"+moveright",         "step right"},
  656. {"+strafe",         "sidestep"},
  657. {"+lookup",         "look up"},
  658. {"+lookdown",         "look down"},
  659. {"centerview",         "center view"},
  660. {"+mlook",             "mouse look"},
  661. {"+klook",             "keyboard look"},
  662. {"+moveup",            "swim up"},
  663. {"+movedown",        "swim down"}
  664. };
  665.  
  666. #define    NUMCOMMANDS    (sizeof(bindnames)/sizeof(bindnames[0]))
  667.  
  668. int        keys_cursor;
  669. int        bind_grab;
  670.  
  671. void M_Menu_Keys_f (void)
  672. {
  673.     key_dest = key_menu;
  674.     m_state = m_keys;
  675.     m_entersound = true;
  676. }
  677.  
  678.  
  679. void M_FindKeysForCommand (char *command, int *twokeys)
  680. {
  681.     int        count;
  682.     int        j;
  683.     int        l;
  684.     char    *b;
  685.  
  686.     twokeys[0] = twokeys[1] = -1;
  687.     l = strlen(command);
  688.     count = 0;
  689.  
  690.     for (j=0 ; j<256 ; j++)
  691.     {
  692.         b = keybindings[j];
  693.         if (!b)
  694.             continue;
  695.         if (!strncmp (b, command, l) )
  696.         {
  697.             twokeys[count] = j;
  698.             count++;
  699.             if (count == 2)
  700.                 break;
  701.         }
  702.     }
  703. }
  704.  
  705. void M_UnbindCommand (char *command)
  706. {
  707.     int        j;
  708.     int        l;
  709.     char    *b;
  710.  
  711.     l = strlen(command);
  712.  
  713.     for (j=0 ; j<256 ; j++)
  714.     {
  715.         b = keybindings[j];
  716.         if (!b)
  717.             continue;
  718.         if (!strncmp (b, command, l) )
  719.             Key_SetBinding (j, "");
  720.     }
  721. }
  722.  
  723.  
  724. void M_Keys_Draw (void)
  725. {
  726.     int        i, l;
  727.     int        keys[2];
  728.     char    *name;
  729.     int        x, y;
  730.     qpic_t    *p;
  731.  
  732.     p = Draw_CachePic ("gfx/ttl_cstm.lmp");
  733.     M_DrawPic ( (320-p->width)/2, 4, p);
  734.  
  735.     if (bind_grab)
  736.         M_Print (12, 32, "Press a key or button for this action");
  737.     else
  738.         M_Print (18, 32, "Enter to change, backspace to clear");
  739.         
  740. // search for known bindings
  741.     for (i=0 ; i<NUMCOMMANDS ; i++)
  742.     {
  743.         y = 48 + 8*i;
  744.  
  745.         M_Print (16, y, bindnames[i][1]);
  746.  
  747.         l = strlen (bindnames[i][0]);
  748.         
  749.         M_FindKeysForCommand (bindnames[i][0], keys);
  750.         
  751.         if (keys[0] == -1)
  752.         {
  753.             M_Print (140, y, "???");
  754.         }
  755.         else
  756.         {
  757.             name = Key_KeynumToString (keys[0]);
  758.             M_Print (140, y, name);
  759.             x = strlen(name) * 8;
  760.             if (keys[1] != -1)
  761.             {
  762.                 M_Print (140 + x + 8, y, "or");
  763.                 M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
  764.             }
  765.         }
  766.     }
  767.     
  768.     if (bind_grab)
  769.         M_DrawCharacter (130, 48 + keys_cursor*8, '=');
  770.     else
  771.         M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
  772. }
  773.  
  774.  
  775. void M_Keys_Key (int k)
  776. {
  777.     char    cmd[80];
  778.     int        keys[2];
  779.     
  780.     if (bind_grab)
  781.     {    // defining a key
  782.         S_LocalSound ("misc/menu1.wav");
  783.         if (k == K_ESCAPE)
  784.         {
  785.             bind_grab = false;
  786.         }
  787.         else if (k != '`')
  788.         {
  789.             sprintf (cmd, "bind %s \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);            
  790.             Cbuf_InsertText (cmd);
  791.         }
  792.         
  793.         bind_grab = false;
  794.         return;
  795.     }
  796.     
  797.     switch (k)
  798.     {
  799.     case K_ESCAPE:
  800.         M_Menu_Options_f ();
  801.         break;
  802.  
  803.     case K_LEFTARROW:
  804.     case K_UPARROW:
  805.         S_LocalSound ("misc/menu1.wav");
  806.         keys_cursor--;
  807.         if (keys_cursor < 0)
  808.             keys_cursor = NUMCOMMANDS-1;
  809.         break;
  810.  
  811.     case K_DOWNARROW:
  812.     case K_RIGHTARROW:
  813.         S_LocalSound ("misc/menu1.wav");
  814.         keys_cursor++;
  815.         if (keys_cursor >= NUMCOMMANDS)
  816.             keys_cursor = 0;
  817.         break;
  818.  
  819.     case K_ENTER:        // go into bind mode
  820.         M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
  821.         S_LocalSound ("misc/menu2.wav");
  822.         if (keys[1] != -1)
  823.             M_UnbindCommand (bindnames[keys_cursor][0]);
  824.         bind_grab = true;
  825.         break;
  826.  
  827.     case K_BACKSPACE:        // delete bindings
  828.     case K_DEL:                // delete bindings
  829.         S_LocalSound ("misc/menu2.wav");
  830.         M_UnbindCommand (bindnames[keys_cursor][0]);
  831.         break;
  832.     }
  833. }
  834.  
  835. //=============================================================================
  836. /* VIDEO MENU */
  837.  
  838. void M_Menu_Video_f (void)
  839. {
  840.     key_dest = key_menu;
  841.     m_state = m_video;
  842.     m_entersound = true;
  843. }
  844.  
  845.  
  846. void M_Video_Draw (void)
  847. {
  848.     (*vid_menudrawfn) ();
  849. }
  850.  
  851.  
  852. void M_Video_Key (int key)
  853. {
  854.     (*vid_menukeyfn) (key);
  855. }
  856.  
  857. //=============================================================================
  858. /* HELP MENU */
  859.  
  860. int        help_page;
  861. #define    NUM_HELP_PAGES    6
  862.  
  863.  
  864. void M_Menu_Help_f (void)
  865. {
  866.     key_dest = key_menu;
  867.     m_state = m_help;
  868.     m_entersound = true;
  869.     help_page = 0;
  870. }
  871.  
  872.  
  873.  
  874. void M_Help_Draw (void)
  875. {
  876.     M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
  877. }
  878.  
  879.  
  880. void M_Help_Key (int key)
  881. {
  882.     switch (key)
  883.     {
  884.     case K_ESCAPE:
  885.         M_Menu_Main_f ();
  886.         break;
  887.         
  888.     case K_UPARROW:
  889.     case K_RIGHTARROW:
  890.         m_entersound = true;
  891.         if (++help_page >= NUM_HELP_PAGES)
  892.             help_page = 0;
  893.         break;
  894.  
  895.     case K_DOWNARROW:
  896.     case K_LEFTARROW:
  897.         m_entersound = true;
  898.         if (--help_page < 0)
  899.             help_page = NUM_HELP_PAGES-1;
  900.         break;
  901.     }
  902.  
  903. }
  904.  
  905. //=============================================================================
  906. /* QUIT MENU */
  907.  
  908. int        msgNumber;
  909. int        m_quit_prevstate;
  910. qboolean    wasInMenus;
  911.  
  912. char *quitMessage [] = 
  913. {
  914. /* .........1.........2.... */
  915.   "  Are you gonna quit    ",
  916.   "  this game just like   ",
  917.   "   everything else?     ",
  918.   "                        ",
  919.  
  920.   " Milord, methinks that  ",
  921.   "   thou art a lowly     ",
  922.   " quitter. Is this true? ",
  923.   "                        ",
  924.  
  925.   " Do I need to bust your ",
  926.   "  face open for trying  ",
  927.   "        to quit?        ",
  928.   "                        ",
  929.  
  930.   " Man, I oughta smack you",
  931.   "   for trying to quit!  ",
  932.   "     Press Y to get     ",
  933.   "      smacked out.      ",
  934.  
  935.   " Press Y to quit like a ",
  936.   "   big loser in life.   ",
  937.   "  Press N to stay proud ",
  938.   "    and successful!     ",
  939.  
  940.   "   If you press Y to    ",
  941.   "  quit, I will summon   ",
  942.   "  Satan all over your   ",
  943.   "      hard drive!       ",
  944.  
  945.   "  Um, Asmodeus dislikes ",
  946.   " his children trying to ",
  947.   " quit. Press Y to return",
  948.   "   to your Tinkertoys.  ",
  949.  
  950.   "  If you quit now, I'll ",
  951.   "  throw a blanket-party ",
  952.   "   for you next time!   ",
  953.   "                        "
  954. };
  955.  
  956. void M_Menu_Quit_f (void)
  957. {
  958.     if (m_state == m_quit)
  959.         return;
  960.     wasInMenus = (key_dest == key_menu);
  961.     key_dest = key_menu;
  962.     m_quit_prevstate = m_state;
  963.     m_state = m_quit;
  964.     m_entersound = true;
  965.     msgNumber = rand()&7;
  966. }
  967.  
  968.  
  969. void M_Quit_Key (int key)
  970. {
  971.     switch (key)
  972.     {
  973.     case K_ESCAPE:
  974.     case 'n':
  975.     case 'N':
  976.         if (wasInMenus)
  977.         {
  978.             m_state = m_quit_prevstate;
  979.             m_entersound = true;
  980.         }
  981.         else
  982.         {
  983.             key_dest = key_game;
  984.             m_state = m_none;
  985.         }
  986.         break;
  987.  
  988.     case 'Y':
  989.     case 'y':
  990.         key_dest = key_console;
  991.         CL_Disconnect ();
  992.         Sys_Quit ();
  993.         break;
  994.  
  995.     default:
  996.         break;
  997.     }
  998.  
  999. }
  1000.  
  1001. void M_Menu_SinglePlayer_f (void) {
  1002.     m_state = m_singleplayer;
  1003. }
  1004.  
  1005. void M_SinglePlayer_Draw (void) {
  1006.     qpic_t    *p;
  1007.  
  1008.     M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  1009. //    M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  1010.     p = Draw_CachePic ("gfx/ttl_sgl.lmp");
  1011.     M_DrawPic ( (320-p->width)/2, 4, p);
  1012. //    M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
  1013.  
  1014.     M_DrawTextBox (60, 10*8, 23, 4);    
  1015.     M_PrintWhite (92, 12*8, "QuakeWorld is for");
  1016.     M_PrintWhite (88, 13*8, "Internet play only");
  1017.  
  1018. }
  1019.  
  1020. void M_SinglePlayer_Key (key) {
  1021.     if (key == K_ESCAPE || key==K_ENTER)
  1022.         m_state = m_main;
  1023. }
  1024.  
  1025. void M_Menu_MultiPlayer_f (void) {
  1026.     m_state = m_multiplayer;
  1027. }
  1028.  
  1029. void M_MultiPlayer_Draw (void) {
  1030.     qpic_t    *p;
  1031.  
  1032.     M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  1033. //    M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
  1034.     p = Draw_CachePic ("gfx/p_multi.lmp");
  1035.     M_DrawPic ( (320-p->width)/2, 4, p);
  1036. //    M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
  1037.  
  1038.     M_DrawTextBox (46, 8*8, 27, 9);    
  1039.     M_PrintWhite (72, 10*8, "If you want to find QW  ");
  1040.     M_PrintWhite (72, 11*8, "games, head on over to: ");
  1041.          M_Print (72, 12*8, "   www.quakeworld.net   ");
  1042.     M_PrintWhite (72, 13*8, "          or            ");
  1043.          M_Print (72, 14*8, "   www.quakespy.com     ");
  1044.     M_PrintWhite (72, 15*8, "For pointers on getting ");
  1045.     M_PrintWhite (72, 16*8, "        started!        ");
  1046. }
  1047.  
  1048. void M_MultiPlayer_Key (key) {
  1049.     if (key == K_ESCAPE || key==K_ENTER)
  1050.         m_state = m_main;
  1051. }
  1052.  
  1053. void M_Quit_Draw (void)
  1054. {
  1055. #define VSTR(x) #x
  1056. #define VSTR2(x) VSTR(x)
  1057.     char *cmsg[] = {
  1058. //    0123456789012345678901234567890123456789
  1059.     "0            QuakeWorld",
  1060.     "1    version " VSTR2(VERSION) " by id Software",
  1061.     "0Programming",
  1062.     "1 John Carmack    Michael Abrash",
  1063.     "1 John Cash       Christian Antkow",
  1064.     "0Additional Programming",
  1065.     "1 Dave 'Zoid' Kirsch",
  1066.     "1 Jack 'morbid' Mathews",
  1067.     "0Id Software is not responsible for",
  1068.     "0providing technical support for",
  1069.     "0QUAKEWORLD(tm). (c)1996 Id Software,",
  1070.     "0Inc.  All Rights Reserved.",
  1071.     "0QUAKEWORLD(tm) is a trademark of Id",
  1072.     "0Software, Inc.",
  1073.     "1NOTICE: THE COPYRIGHT AND TRADEMARK",
  1074.     "1NOTICES APPEARING  IN YOUR COPY OF",
  1075.     "1QUAKE(r) ARE NOT MODIFIED BY THE USE",
  1076.     "1OF QUAKEWORLD(tm) AND REMAIN IN FULL",
  1077.     "1FORCE.",
  1078.     "0NIN(r) is a registered trademark",
  1079.     "0licensed to Nothing Interactive, Inc.",
  1080.     "0All rights reserved. Press y to exit",
  1081.     NULL };
  1082.     char **p;
  1083.     int y;
  1084.  
  1085.     if (wasInMenus)
  1086.     {
  1087.         m_state = m_quit_prevstate;
  1088.         m_recursiveDraw = true;
  1089.         M_Draw ();
  1090.         m_state = m_quit;
  1091.     }
  1092. #if 1
  1093.     M_DrawTextBox (0, 0, 38, 23);
  1094.     y = 12;
  1095.     for (p = cmsg; *p; p++, y += 8) {
  1096.         if (**p == '0')
  1097.             M_PrintWhite (16, y, *p + 1);
  1098.         else
  1099.             M_Print (16, y,    *p + 1);
  1100.     }
  1101. #else
  1102.     M_DrawTextBox (56, 76, 24, 4);
  1103.     M_Print (64, 84,  quitMessage[msgNumber*4+0]);
  1104.     M_Print (64, 92,  quitMessage[msgNumber*4+1]);
  1105.     M_Print (64, 100, quitMessage[msgNumber*4+2]);
  1106.     M_Print (64, 108, quitMessage[msgNumber*4+3]);
  1107. #endif
  1108. }
  1109.  
  1110.  
  1111.  
  1112. //=============================================================================
  1113. /* Menu Subsystem */
  1114.  
  1115.  
  1116. void M_Init (void)
  1117. {
  1118.     Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
  1119.  
  1120.     Cmd_AddCommand ("menu_main", M_Menu_Main_f);
  1121.     Cmd_AddCommand ("menu_options", M_Menu_Options_f);
  1122.     Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
  1123.     Cmd_AddCommand ("menu_video", M_Menu_Video_f);
  1124.     Cmd_AddCommand ("help", M_Menu_Help_f);
  1125.     Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
  1126. }
  1127.  
  1128.  
  1129. void M_Draw (void)
  1130. {
  1131.     if (m_state == m_none || key_dest != key_menu)
  1132.         return;
  1133.  
  1134.     if (!m_recursiveDraw)
  1135.     {
  1136.         scr_copyeverything = 1;
  1137.  
  1138.         if (scr_con_current)
  1139.         {
  1140.             Draw_ConsoleBackground (vid.height);
  1141.             VID_UnlockBuffer ();
  1142.             S_ExtraUpdate ();
  1143.             VID_LockBuffer ();
  1144.         }
  1145.         else
  1146.             Draw_FadeScreen ();
  1147.  
  1148.         scr_fullupdate = 0;
  1149.     }
  1150.     else
  1151.     {
  1152.         m_recursiveDraw = false;
  1153.     }
  1154.  
  1155.     switch (m_state)
  1156.     {
  1157.     case m_none:
  1158.         break;
  1159.  
  1160.     case m_main:
  1161.         M_Main_Draw ();
  1162.         break;
  1163.  
  1164.     case m_singleplayer:
  1165.         M_SinglePlayer_Draw ();
  1166.         break;
  1167.  
  1168.     case m_load:
  1169. //        M_Load_Draw ();
  1170.         break;
  1171.  
  1172.     case m_save:
  1173. //        M_Save_Draw ();
  1174.         break;
  1175.  
  1176.     case m_multiplayer:
  1177.         M_MultiPlayer_Draw ();
  1178.         break;
  1179.  
  1180.     case m_setup:
  1181. //        M_Setup_Draw ();
  1182.         break;
  1183.  
  1184.     case m_net:
  1185. //        M_Net_Draw ();
  1186.         break;
  1187.  
  1188.     case m_options:
  1189.         M_Options_Draw ();
  1190.         break;
  1191.  
  1192.     case m_keys:
  1193.         M_Keys_Draw ();
  1194.         break;
  1195.  
  1196.     case m_video:
  1197.         M_Video_Draw ();
  1198.         break;
  1199.  
  1200.     case m_help:
  1201.         M_Help_Draw ();
  1202.         break;
  1203.  
  1204.     case m_quit:
  1205.         M_Quit_Draw ();
  1206.         break;
  1207.  
  1208.     case m_serialconfig:
  1209. //        M_SerialConfig_Draw ();
  1210.         break;
  1211.  
  1212.     case m_modemconfig:
  1213. //        M_ModemConfig_Draw ();
  1214.         break;
  1215.  
  1216.     case m_lanconfig:
  1217. //        M_LanConfig_Draw ();
  1218.         break;
  1219.  
  1220.     case m_gameoptions:
  1221. //        M_GameOptions_Draw ();
  1222.         break;
  1223.  
  1224.     case m_search:
  1225. //        M_Search_Draw ();
  1226.         break;
  1227.  
  1228.     case m_slist:
  1229. //        M_ServerList_Draw ();
  1230.         break;
  1231.     }
  1232.  
  1233.     if (m_entersound)
  1234.     {
  1235.         S_LocalSound ("misc/menu2.wav");
  1236.         m_entersound = false;
  1237.     }
  1238.  
  1239.     VID_UnlockBuffer ();
  1240.     S_ExtraUpdate ();
  1241.     VID_LockBuffer ();
  1242. }
  1243.  
  1244.  
  1245. void M_Keydown (int key)
  1246. {
  1247.     switch (m_state)
  1248.     {
  1249.     case m_none:
  1250.         return;
  1251.  
  1252.     case m_main:
  1253.         M_Main_Key (key);
  1254.         return;
  1255.  
  1256.     case m_singleplayer:
  1257.         M_SinglePlayer_Key (key);
  1258.         return;
  1259.  
  1260.     case m_load:
  1261. //        M_Load_Key (key);
  1262.         return;
  1263.  
  1264.     case m_save:
  1265. //        M_Save_Key (key);
  1266.         return;
  1267.  
  1268.     case m_multiplayer:
  1269.         M_MultiPlayer_Key (key);
  1270.         return;
  1271.  
  1272.     case m_setup:
  1273. //        M_Setup_Key (key);
  1274.         return;
  1275.  
  1276.     case m_net:
  1277. //        M_Net_Key (key);
  1278.         return;
  1279.  
  1280.     case m_options:
  1281.         M_Options_Key (key);
  1282.         return;
  1283.  
  1284.     case m_keys:
  1285.         M_Keys_Key (key);
  1286.         return;
  1287.  
  1288.     case m_video:
  1289.         M_Video_Key (key);
  1290.         return;
  1291.  
  1292.     case m_help:
  1293.         M_Help_Key (key);
  1294.         return;
  1295.  
  1296.     case m_quit:
  1297.         M_Quit_Key (key);
  1298.         return;
  1299.  
  1300.     case m_serialconfig:
  1301. //        M_SerialConfig_Key (key);
  1302.         return;
  1303.  
  1304.     case m_modemconfig:
  1305. //        M_ModemConfig_Key (key);
  1306.         return;
  1307.  
  1308.     case m_lanconfig:
  1309. //        M_LanConfig_Key (key);
  1310.         return;
  1311.  
  1312.     case m_gameoptions:
  1313. //        M_GameOptions_Key (key);
  1314.         return;
  1315.  
  1316.     case m_search:
  1317. //        M_Search_Key (key);
  1318.         break;
  1319.  
  1320.     case m_slist:
  1321. //        M_ServerList_Key (key);
  1322.         return;
  1323.     }
  1324. }
  1325.  
  1326.  
  1327.