📄 menu.c
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#ifdef _WIN32
#include "winquake.h"
#endif
void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
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;
void M_Menu_Main_f (void);
void M_Menu_SinglePlayer_f (void);
void M_Menu_Load_f (void);
void M_Menu_Save_f (void);
void M_Menu_MultiPlayer_f (void);
void M_Menu_Setup_f (void);
void M_Menu_Net_f (void);
void M_Menu_Options_f (void);
void M_Menu_Keys_f (void);
void M_Menu_Video_f (void);
void M_Menu_Help_f (void);
void M_Menu_Quit_f (void);
void M_Menu_SerialConfig_f (void);
void M_Menu_ModemConfig_f (void);
void M_Menu_LanConfig_f (void);
void M_Menu_GameOptions_f (void);
void M_Menu_Search_f (void);
void M_Menu_ServerList_f (void);
void M_Main_Draw (void);
void M_SinglePlayer_Draw (void);
void M_Load_Draw (void);
void M_Save_Draw (void);
void M_MultiPlayer_Draw (void);
void M_Setup_Draw (void);
void M_Net_Draw (void);
// void M_Options_Draw (void); // 2002-01-31 New menu system by Maddes
void M_Keys_Draw (void);
void M_Video_Draw (void);
void M_Help_Draw (void);
void M_Quit_Draw (void);
void M_SerialConfig_Draw (void);
void M_ModemConfig_Draw (void);
void M_LanConfig_Draw (void);
void M_GameOptions_Draw (void);
void M_Search_Draw (void);
void M_ServerList_Draw (void);
void M_Main_Key (int key);
void M_SinglePlayer_Key (int key);
void M_Load_Key (int key);
void M_Save_Key (int key);
void M_MultiPlayer_Key (int key);
void M_Setup_Key (int key);
void M_Net_Key (int key);
// void M_Options_Key (int key); // 2002-01-31 New menu system by Maddes
void M_Keys_Key (int key);
void M_Video_Key (int key);
void M_Help_Key (int key);
void M_Quit_Key (int key);
void M_SerialConfig_Key (int key);
void M_ModemConfig_Key (int key);
void M_LanConfig_Key (int key);
void M_GameOptions_Key (int key);
void M_Search_Key (int key);
void M_ServerList_Key (int key);
qboolean m_entersound; // play after drawing a frame, so caching
// won't disrupt the sound
qboolean m_recursiveDraw;
int m_return_state;
qboolean m_return_onerror;
char m_return_reason [32];
#define StartingGame (m_multiplayer_cursor == 1)
#define JoiningGame (m_multiplayer_cursor == 0)
#define SerialConfig (m_net_cursor == 0)
#define DirectConfig (m_net_cursor == 1)
#define IPXConfig (m_net_cursor == 2)
#define TCPIPConfig (m_net_cursor == 3)
void M_ConfigureNetSubsystem(void);
// 2002-01-31 New menu system by Maddes start
// menu entry types
#define MENU_SELECTABLE 0
#define MENU_DRAW_ONLY 1
#define MENU_INVISIBLE 2
typedef struct menu_definition_s
{
int funcno; // Unique number used for displaying and executing a menu entry. Zero = end of menu definition
// First entry in menu definition defines the ESC function
int type; // Entry type flag, use above DEFINEs and M_Menu_DrawCheck()
} menu_definition_t;
// data of current displayed menu
int *current_cursor;
menu_definition_t *current_menu;
int menu_last_index, menu_first_index;
// function number definitions
// Menus
#define MENU_OFF 1
#define MENU_MAIN 2
#define MENU_SINGLEPLAYER 3
#define MENU_MULTIPLAYER 4
#define MENU_OPTIONS 5
#define MENU_HELP 6
#define MENU_QUIT 7
// Options
#define MENU_CUSTOMIZE_CONTROLS 101
#define MENU_GO_TO_CONSOLE 102
#define MENU_LOAD_DEFAULT_CFG 103
#define MENU_SCREENSIZE 104
#define MENU_BRIGHTNESS 105
#define MENU_MOUSESPEED 106
#define MENU_CD_VOLUME 107
#define MENU_SOUND_VOLUME 108
#define MENU_ALWAYS_RUN 109
#define MENU_INVERT_MOUSE 110
#define MENU_LOOKSPRING 111
#define MENU_LOOKSTRAFE 112
#define MENU_VIDEO_RESOLUTION 113
#define MENU_USE_MOUSE 114
#define MENU_CONTROL_OPTIONS 120
#define MENU_MOUSELOOK 121
#define MENU_SOUND_OPTIONS 130
#define MENU_EXTERNAL_DATA 140
#define MENU_EXTERNAL_ENT 141
#define MENU_EXTERNAL_VIS 142
#define MENU_EXTERNAL_LIT 143
#define MENU_CLIENT_OPTIONS 150
#define MENU_CL_ENTITIES_MIN 151
#define MENU_CL_ENTITIES_TEMP_MIN 152
#define MENU_CL_ENTITIES_STATIC_MIN 153
#define MENU_CL_COMPATIBILITY 154
#define MENU_SERVER_OPTIONS 160
#define MENU_SV_ENTITIES 161
#define MENU_SV_ENTITIES_TEMP 162
#define MENU_SV_ENTITIES_STATIC 163
#define MENU_SV_ENTITIES_COPY_TO_CL 164
#define MENU_PR_ZONE_MIN_STRINGS 165
#define MENU_BUILTIN_REMAP 166
#define MENU_SV_COMPATIBILITY 167
#define MENU_NVS_ENABLE 168
#define MENU_VIDEO_OPTIONS 170
#define MENU_CON_ALPHA 171
#define MENU_CON_HEIGHT 172
#define MENU_SHOW_FPS 173
#define MENU_GL_MAXDEPTH 174
// menu definitions
int options_cursor;
menu_definition_t m_menu_options[] =
{ // Options Menu
{MENU_MAIN, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_CUSTOMIZE_CONTROLS, MENU_SELECTABLE},
{MENU_GO_TO_CONSOLE, MENU_SELECTABLE},
{MENU_LOAD_DEFAULT_CFG, MENU_SELECTABLE},
{MENU_CONTROL_OPTIONS, MENU_SELECTABLE},
{MENU_SOUND_OPTIONS, MENU_SELECTABLE},
{MENU_EXTERNAL_DATA, MENU_SELECTABLE},
{MENU_CLIENT_OPTIONS, MENU_SELECTABLE},
{MENU_SERVER_OPTIONS, MENU_SELECTABLE},
{MENU_VIDEO_OPTIONS, MENU_SELECTABLE},
{MENU_VIDEO_RESOLUTION, MENU_SELECTABLE},
{0, 0}, // end of submenu
};
int control_options_cursor;
menu_definition_t m_menu_control_options[] =
{ // Control Options
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_ALWAYS_RUN, MENU_SELECTABLE},
{MENU_MOUSELOOK, MENU_SELECTABLE},
{MENU_LOOKSPRING, MENU_SELECTABLE},
{MENU_LOOKSTRAFE, MENU_SELECTABLE},
{MENU_MOUSESPEED, MENU_SELECTABLE},
{MENU_INVERT_MOUSE, MENU_SELECTABLE},
#ifdef _WIN32
{MENU_USE_MOUSE, MENU_INVISIBLE}, // only present in windowed mode on Win32
#endif
{0, 0}, // end of submenu
};
int sound_options_cursor;
menu_definition_t m_menu_sound_options[] =
{ // Sound Options
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_CD_VOLUME, MENU_SELECTABLE},
{MENU_SOUND_VOLUME, MENU_SELECTABLE},
{0, 0}, // end of submenu
};
int external_data_cursor;
menu_definition_t m_menu_external_data[] =
{ // External Data
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_EXTERNAL_ENT, MENU_SELECTABLE},
{MENU_EXTERNAL_VIS, MENU_SELECTABLE},
#ifdef GLQUAKE
{MENU_EXTERNAL_LIT, MENU_SELECTABLE}, // only useful in GLQuake
#endif
{0, 0}, // end of submenu
};
int client_options_cursor;
menu_definition_t m_menu_client_options[] =
{ // Client Options
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_CL_ENTITIES_MIN, MENU_SELECTABLE},
{MENU_CL_ENTITIES_TEMP_MIN, MENU_SELECTABLE},
{MENU_CL_ENTITIES_STATIC_MIN, MENU_SELECTABLE},
{MENU_CL_COMPATIBILITY, MENU_SELECTABLE},
{0, 0}, // end of submenu
};
int server_options_cursor;
menu_definition_t m_menu_server_options[] =
{ // Server Options
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_SV_ENTITIES, MENU_SELECTABLE},
{MENU_SV_ENTITIES_TEMP, MENU_SELECTABLE},
{MENU_SV_ENTITIES_STATIC, MENU_SELECTABLE},
{MENU_SV_ENTITIES_COPY_TO_CL, MENU_SELECTABLE},
{MENU_PR_ZONE_MIN_STRINGS, MENU_SELECTABLE},
{MENU_BUILTIN_REMAP, MENU_SELECTABLE},
{MENU_SV_COMPATIBILITY, MENU_SELECTABLE},
{MENU_NVS_ENABLE, MENU_SELECTABLE},
{0, 0}, // end of submenu
};
int video_options_cursor;
menu_definition_t m_menu_video_options[] =
{ // Video Options
{MENU_OPTIONS, MENU_OPTIONS}, // this is the ESC key function and title
{MENU_SCREENSIZE, MENU_SELECTABLE},
{MENU_BRIGHTNESS, MENU_SELECTABLE},
{MENU_CON_ALPHA, MENU_SELECTABLE},
{MENU_CON_HEIGHT, MENU_SELECTABLE},
{MENU_SHOW_FPS, MENU_SELECTABLE},
#ifdef GLQUAKE
{MENU_GL_MAXDEPTH, MENU_SELECTABLE},
#endif
#ifdef _WIN32
{MENU_USE_MOUSE, MENU_INVISIBLE}, // only present in windowed mode on Win32
#endif
{0, 0}, // end of submenu
};
// 2002-01-31 New menu system by Maddes end
/*
================
M_DrawCharacter
Draws one solid graphics character
================
*/
void M_DrawCharacter (int cx, int line, int num)
{
Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
}
void M_Print (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, (*str)+128);
str++;
cx += 8;
}
}
void M_PrintWhite (int cx, int cy, char *str)
{
while (*str)
{
M_DrawCharacter (cx, cy, *str);
str++;
cx += 8;
}
}
void M_DrawTransPic (int x, int y, qpic_t *pic)
{
Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
}
void M_DrawPic (int x, int y, qpic_t *pic)
{
Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
}
byte identityTable[256];
byte translationTable[256];
void M_BuildTranslationTable(int top, int bottom)
{
int j;
byte *dest, *source;
for (j = 0; j < 256; j++)
identityTable[j] = j;
dest = translationTable;
source = identityTable;
memcpy (dest, source, 256);
if (top < 128) // the artists made some backwards ranges. sigh.
memcpy (dest + TOP_RANGE, source + top, 16);
else
for (j=0 ; j<16 ; j++)
dest[TOP_RANGE+j] = source[top+15-j];
if (bottom < 128)
memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
else
for (j=0 ; j<16 ; j++)
dest[BOTTOM_RANGE+j] = source[bottom+15-j];
}
void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
{
Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
}
void M_DrawTextBox (int x, int y, int width, int lines)
{
qpic_t *p;
int cx, cy;
int n;
// draw left side
cx = x;
cy = y;
p = Draw_CachePic ("gfx/box_tl.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_ml.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bl.lmp");
M_DrawTransPic (cx, cy+8, p);
// draw middle
cx += 8;
while (width > 0)
{
cy = y;
p = Draw_CachePic ("gfx/box_tm.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mm.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
if (n == 1)
p = Draw_CachePic ("gfx/box_mm2.lmp");
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bm.lmp");
M_DrawTransPic (cx, cy+8, p);
width -= 2;
cx += 16;
}
// draw right side
cy = y;
p = Draw_CachePic ("gfx/box_tr.lmp");
M_DrawTransPic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mr.lmp");
for (n = 0; n < lines; n++)
{
cy += 8;
M_DrawTransPic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_br.lmp");
M_DrawTransPic (cx, cy+8, p);
}
//=============================================================================
int m_save_demonum;
/*
================
M_ToggleMenu_f
================
*/
void M_ToggleMenu_f (void)
{
m_entersound = true;
if (key_dest == key_menu)
{
if (m_state != m_main)
{
M_Menu_Main_f ();
return;
}
key_dest = key_game;
m_state = m_none;
return;
}
if (key_dest == key_console)
{
Con_ToggleConsole_f ();
}
else
{
M_Menu_Main_f ();
}
}
//=============================================================================
/* MAIN MENU */
int m_main_cursor;
#define MAIN_ITEMS 5
void M_Menu_Main_f (void)
{
if (key_dest != key_menu)
{
m_save_demonum = cls.demonum;
cls.demonum = -1;
}
key_dest = key_menu;
m_state = m_main;
m_entersound = true;
}
void M_Main_Draw (void)
{
int f;
qpic_t *p;
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/ttl_main.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
// f = (int)(host_time * 10)%6;
f = (int)(realtime * 10)%6;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
}
void M_Main_Key (int key)
{
switch (key)
{
case K_ESCAPE:
key_dest = key_game;
m_state = m_none;
cls.demonum = m_save_demonum;
if (cls.demonum != -1 && !cls.demoplayback && cls.state != ca_connected)
CL_NextDemo ();
break;
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_main_cursor >= MAIN_ITEMS)
m_main_cursor = 0;
break;
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
if (--m_main_cursor < 0)
m_main_cursor = MAIN_ITEMS - 1;
break;
case K_ENTER:
m_entersound = true;
switch (m_main_cursor)
{
case 0:
M_Menu_SinglePlayer_f ();
break;
case 1:
M_Menu_MultiPlayer_f ();
break;
case 2:
M_Menu_Options_f ();
break;
case 3:
M_Menu_Help_f ();
break;
case 4:
M_Menu_Quit_f ();
break;
}
}
}
//=============================================================================
/* SINGLE PLAYER MENU */
int m_singleplayer_cursor;
#define SINGLEPLAYER_ITEMS 3
void M_Menu_SinglePlayer_f (void)
{
key_dest = key_menu;
m_state = m_singleplayer;
m_entersound = true;
}
void M_SinglePlayer_Draw (void)
{
int f;
qpic_t *p;
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/ttl_sgl.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
// f = (int)(host_time * 10)%6;
f = (int)(realtime * 10)%6;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
M_DrawTransPic (54, 32 + m_singleplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
}
void M_SinglePlayer_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_Main_f ();
break;
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS)
m_singleplayer_cursor = 0;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -