cs16-client-legacy/mainui/menu_langame.cpp

476 lines
15 KiB
C++
Raw Normal View History

/*
Copyright (C) 1997-2001 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 "extdll.h"
#include "basemenu.h"
#include "utils.h"
#include "keydefs.h"
#include "menu_btnsbmp_table.h"
#define ART_BANNER "gfx/shell/head_lan"
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_JOINGAME 2
#define ID_CREATEGAME 3
#define ID_GAMEINFO 4
#define ID_REFRESH 5
#define ID_DONE 6
#define ID_SERVERSLIST 7
#define ID_TABLEHINT 8
#define ID_MSGBOX 9
#define ID_MSGTEXT 10
#define ID_YES 130
#define ID_NO 131
#define GAME_LENGTH 18
#define MAPNAME_LENGTH 20+GAME_LENGTH
#define TYPE_LENGTH 16+MAPNAME_LENGTH
#define MAXCL_LENGTH 15+TYPE_LENGTH
typedef struct
{
char gameDescription[UI_MAX_SERVERS][256];
char *gameDescriptionPtr[UI_MAX_SERVERS];
menuFramework_s menu;
menuBitmap_s background;
menuBitmap_s banner;
menuPicButton_s joinGame;
menuPicButton_s createGame;
menuPicButton_s gameInfo;
menuPicButton_s refresh;
menuPicButton_s done;
// joingame prompt dialog
menuAction_s msgBox;
menuAction_s dlgMessage1;
menuAction_s dlgMessage2;
menuPicButton_s yes;
menuPicButton_s no;
menuScrollList_s gameList;
menuAction_s hintMessage;
char hintText[MAX_HINT_TEXT];
int refreshTime;
} uiLanGame_t;
static uiLanGame_t uiLanGame;
static void UI_PromptDialog( void )
{
// toggle main menu between active\inactive
// show\hide quit dialog
uiLanGame.joinGame.generic.flags ^= QMF_INACTIVE;
uiLanGame.createGame.generic.flags ^= QMF_INACTIVE;
uiLanGame.gameInfo.generic.flags ^= QMF_INACTIVE;
uiLanGame.refresh.generic.flags ^= QMF_INACTIVE;
uiLanGame.done.generic.flags ^= QMF_INACTIVE;
uiLanGame.gameList.generic.flags ^= QMF_INACTIVE;
uiLanGame.msgBox.generic.flags ^= QMF_HIDDEN;
uiLanGame.dlgMessage1.generic.flags ^= QMF_HIDDEN;
uiLanGame.dlgMessage2.generic.flags ^= QMF_HIDDEN;
uiLanGame.no.generic.flags ^= QMF_HIDDEN;
uiLanGame.yes.generic.flags ^= QMF_HIDDEN;
}
/*
=================
UI_LanGame_KeyFunc
=================
*/
static const char *UI_LanGame_KeyFunc( int key, int down )
{
if( down && key == K_ESCAPE && !( uiLanGame.dlgMessage1.generic.flags & QMF_HIDDEN ))
{
UI_PromptDialog();
return uiSoundNull;
}
return UI_DefaultKey( &uiLanGame.menu, key, down );
}
/*
=================
UI_LanGame_GetGamesList
=================
*/
static void UI_LanGame_GetGamesList( void )
{
int i;
const char *info;
for( i = 0; i < uiStatic.numServers; i++ )
{
if( i >= UI_MAX_SERVERS ) break;
info = uiStatic.serverNames[i];
#if 1
// NOTE: Xash3D is support hot switching between games in multiplayer
// but this feature not detail tested and may be bugly
if( stricmp( gMenu.m_gameinfo.gamefolder, Info_ValueForKey( info, "gamedir" )))
continue; // filter by game
#endif
StringConcat( uiLanGame.gameDescription[i], Info_ValueForKey( info, "host" ), GAME_LENGTH );
StringConcat( uiLanGame.gameDescription[i], uiEmptyString, GAME_LENGTH );
StringConcat( uiLanGame.gameDescription[i], Info_ValueForKey( info, "map" ), MAPNAME_LENGTH );
StringConcat( uiLanGame.gameDescription[i], uiEmptyString, MAPNAME_LENGTH );
if( !strcmp( Info_ValueForKey( info, "dm" ), "1" ))
StringConcat( uiLanGame.gameDescription[i], "deathmatch", TYPE_LENGTH );
else if( !strcmp( Info_ValueForKey( info, "coop" ), "1" ))
StringConcat( uiLanGame.gameDescription[i], "coop", TYPE_LENGTH );
else if( !strcmp( Info_ValueForKey( info, "team" ), "1" ))
StringConcat( uiLanGame.gameDescription[i], "teamplay", TYPE_LENGTH );
StringConcat( uiLanGame.gameDescription[i], uiEmptyString, TYPE_LENGTH );
StringConcat( uiLanGame.gameDescription[i], Info_ValueForKey( info, "numcl" ), MAXCL_LENGTH );
StringConcat( uiLanGame.gameDescription[i], "\\", MAXCL_LENGTH );
StringConcat( uiLanGame.gameDescription[i], Info_ValueForKey( info, "maxcl" ), MAXCL_LENGTH );
StringConcat( uiLanGame.gameDescription[i], uiEmptyString, MAXCL_LENGTH );
uiLanGame.gameDescriptionPtr[i] = uiLanGame.gameDescription[i];
}
for( ; i < UI_MAX_SERVERS; i++ )
uiLanGame.gameDescriptionPtr[i] = NULL;
uiLanGame.gameList.itemNames = (const char **)uiLanGame.gameDescriptionPtr;
uiLanGame.gameList.numItems = 0; // reset it
if( !uiLanGame.gameList.generic.charHeight )
return; // to avoid divide integer by zero
// count number of items
while( uiLanGame.gameList.itemNames[uiLanGame.gameList.numItems] )
uiLanGame.gameList.numItems++;
// calculate number of visible rows
uiLanGame.gameList.numRows = (uiLanGame.gameList.generic.height2 / uiLanGame.gameList.generic.charHeight) - 2;
if( uiLanGame.gameList.numRows > uiLanGame.gameList.numItems ) uiLanGame.gameList.numRows = uiLanGame.gameList.numItems;
if( uiStatic.numServers )
uiLanGame.joinGame.generic.flags &= ~QMF_GRAYED;
}
/*
=================
UI_LanGame_JoinGame
=================
*/
static void UI_LanGame_JoinGame( void )
{
if( !strlen( uiLanGame.gameDescription[uiLanGame.gameList.curItem] ))
return;
CLIENT_JOIN( uiStatic.serverAddresses[uiLanGame.gameList.curItem] );
}
/*
=================
UI_Background_Ownerdraw
=================
*/
static void UI_Background_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
if( !CVAR_GET_FLOAT( "cl_background" ))
UI_DrawBackground_Callback( self );
if( uiStatic.realTime > uiLanGame.refreshTime )
{
uiLanGame.refreshTime = uiStatic.realTime + 10000; // refresh every 10 secs
UI_RefreshServerList();
}
// serverinfo has been changed update display
if( uiStatic.updateServers )
{
UI_LanGame_GetGamesList ();
uiStatic.updateServers = false;
}
}
/*
=================
UI_MsgBox_Ownerdraw
=================
*/
static void UI_MsgBox_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
UI_FillRect( item->x, item->y, item->width, item->height, uiPromptBgColor );
}
/*
=================
UI_LanGame_Callback
=================
*/
static void UI_LanGame_Callback( void *self, int event )
{
menuCommon_s *item = (menuCommon_s *)self;
if( event != QM_ACTIVATED )
return;
switch( item->id )
{
case ID_JOINGAME:
if( CL_IsActive( ))
UI_PromptDialog();
else UI_LanGame_JoinGame();
break;
case ID_CREATEGAME:
CVAR_SET_FLOAT( "public", 0.0f );
UI_CreateGame_Menu();
break;
case ID_GAMEINFO:
// UNDONE: not implemented
break;
case ID_REFRESH:
UI_RefreshServerList();
break;
case ID_DONE:
UI_PopMenu();
break;
case ID_YES:
UI_LanGame_JoinGame();
break;
case ID_NO:
UI_PromptDialog();
break;
}
}
/*
=================
UI_LanGame_Init
=================
*/
static void UI_LanGame_Init( void )
{
memset( &uiLanGame, 0, sizeof( uiLanGame_t ));
uiLanGame.menu.vidInitFunc = UI_LanGame_Init;
uiLanGame.menu.keyFunc = UI_LanGame_KeyFunc;
StringConcat( uiLanGame.hintText, "Game", GAME_LENGTH );
StringConcat( uiLanGame.hintText, uiEmptyString, GAME_LENGTH );
StringConcat( uiLanGame.hintText, "Map", MAPNAME_LENGTH );
StringConcat( uiLanGame.hintText, uiEmptyString, MAPNAME_LENGTH );
StringConcat( uiLanGame.hintText, "Type", TYPE_LENGTH );
StringConcat( uiLanGame.hintText, uiEmptyString, TYPE_LENGTH );
StringConcat( uiLanGame.hintText, "Num/Max Clients", MAXCL_LENGTH );
StringConcat( uiLanGame.hintText, uiEmptyString, MAXCL_LENGTH );
uiLanGame.background.generic.id = ID_BACKGROUND;
uiLanGame.background.generic.type = QMTYPE_BITMAP;
uiLanGame.background.generic.flags = QMF_INACTIVE;
uiLanGame.background.generic.x = 0;
uiLanGame.background.generic.y = 0;
uiLanGame.background.generic.width = uiStatic.width;
uiLanGame.background.generic.height = 768;
uiLanGame.background.pic = ART_BACKGROUND;
uiLanGame.background.generic.ownerdraw = UI_Background_Ownerdraw;
uiLanGame.banner.generic.id = ID_BANNER;
uiLanGame.banner.generic.type = QMTYPE_BITMAP;
uiLanGame.banner.generic.flags = QMF_INACTIVE|QMF_DRAW_ADDITIVE;
uiLanGame.banner.generic.x = UI_BANNER_POSX;
uiLanGame.banner.generic.y = UI_BANNER_POSY;
uiLanGame.banner.generic.width = UI_BANNER_WIDTH;
uiLanGame.banner.generic.height = UI_BANNER_HEIGHT;
uiLanGame.banner.pic = ART_BANNER;
uiLanGame.joinGame.generic.id = ID_JOINGAME;
uiLanGame.joinGame.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.joinGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED;
uiLanGame.joinGame.generic.x = 72;
uiLanGame.joinGame.generic.y = 230;
uiLanGame.joinGame.generic.name = "Join game";
uiLanGame.joinGame.generic.statusText = "Join to selected game";
uiLanGame.joinGame.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.joinGame, PC_JOIN_GAME );
uiLanGame.createGame.generic.id = ID_CREATEGAME;
uiLanGame.createGame.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.createGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLanGame.createGame.generic.x = 72;
uiLanGame.createGame.generic.y = 280;
uiLanGame.createGame.generic.name = "Create game";
uiLanGame.createGame.generic.statusText = "Create new LAN game";
uiLanGame.createGame.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.createGame, PC_CREATE_GAME );
uiLanGame.gameInfo.generic.id = ID_GAMEINFO;
uiLanGame.gameInfo.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.gameInfo.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED;
uiLanGame.gameInfo.generic.x = 72;
uiLanGame.gameInfo.generic.y = 330;
uiLanGame.gameInfo.generic.name = "View game info";
uiLanGame.gameInfo.generic.statusText = "Get detail game info";
uiLanGame.gameInfo.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.gameInfo, PC_VIEW_GAME_INFO );
uiLanGame.refresh.generic.id = ID_REFRESH;
uiLanGame.refresh.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.refresh.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLanGame.refresh.generic.x = 72;
uiLanGame.refresh.generic.y = 380;
uiLanGame.refresh.generic.name = "Refresh";
uiLanGame.refresh.generic.statusText = "Refresh servers list";
uiLanGame.refresh.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.refresh, PC_REFRESH );
uiLanGame.done.generic.id = ID_DONE;
uiLanGame.done.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.done.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLanGame.done.generic.x = 72;
uiLanGame.done.generic.y = 430;
uiLanGame.done.generic.name = "Done";
uiLanGame.done.generic.statusText = "Return to main menu";
uiLanGame.done.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.done, PC_DONE );
uiLanGame.msgBox.generic.id = ID_MSGBOX;
uiLanGame.msgBox.generic.type = QMTYPE_ACTION;
uiLanGame.msgBox.generic.flags = QMF_INACTIVE|QMF_HIDDEN;
uiLanGame.msgBox.generic.ownerdraw = UI_MsgBox_Ownerdraw; // just a fill rectangle
uiLanGame.msgBox.generic.x = DLG_X + 192;
uiLanGame.msgBox.generic.y = 256;
uiLanGame.msgBox.generic.width = 640;
uiLanGame.msgBox.generic.height = 256;
uiLanGame.dlgMessage1.generic.id = ID_MSGTEXT;
uiLanGame.dlgMessage1.generic.type = QMTYPE_ACTION;
uiLanGame.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW;
uiLanGame.dlgMessage1.generic.name = "Join a network game will exit";
uiLanGame.dlgMessage1.generic.x = DLG_X + 248;
uiLanGame.dlgMessage1.generic.y = 280;
uiLanGame.dlgMessage2.generic.id = ID_MSGTEXT;
uiLanGame.dlgMessage2.generic.type = QMTYPE_ACTION;
uiLanGame.dlgMessage2.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW;
uiLanGame.dlgMessage2.generic.name = "any current game, OK to exit?";
uiLanGame.dlgMessage2.generic.x = DLG_X + 248;
uiLanGame.dlgMessage2.generic.y = 310;
uiLanGame.yes.generic.id = ID_YES;
uiLanGame.yes.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.yes.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW;
uiLanGame.yes.generic.name = "Ok";
uiLanGame.yes.generic.x = DLG_X + 380;
uiLanGame.yes.generic.y = 460;
uiLanGame.yes.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.yes, PC_OK );
uiLanGame.no.generic.id = ID_NO;
uiLanGame.no.generic.type = QMTYPE_BM_BUTTON;
uiLanGame.no.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW;
uiLanGame.no.generic.name = "Cancel";
uiLanGame.no.generic.x = DLG_X + 530;
uiLanGame.no.generic.y = 460;
uiLanGame.no.generic.callback = UI_LanGame_Callback;
UI_UtilSetupPicButton( &uiLanGame.no, PC_CANCEL );
uiLanGame.hintMessage.generic.id = ID_TABLEHINT;
uiLanGame.hintMessage.generic.type = QMTYPE_ACTION;
uiLanGame.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
uiLanGame.hintMessage.generic.color = uiColorHelp;
uiLanGame.hintMessage.generic.name = uiLanGame.hintText;
uiLanGame.hintMessage.generic.x = 360;
uiLanGame.hintMessage.generic.y = 225;
uiLanGame.gameList.generic.id = ID_SERVERSLIST;
uiLanGame.gameList.generic.type = QMTYPE_SCROLLLIST;
uiLanGame.gameList.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_SMALLFONT;
uiLanGame.gameList.generic.x = 360;
uiLanGame.gameList.generic.y = 255;
uiLanGame.gameList.generic.width = 640;
uiLanGame.gameList.generic.height = 440;
uiLanGame.gameList.generic.callback = UI_LanGame_Callback;
uiLanGame.gameList.itemNames = (const char **)uiLanGame.gameDescriptionPtr;
// server.dll needs for reading savefiles or startup newgame
if( !CheckGameDll( ))
uiLanGame.createGame.generic.flags |= QMF_GRAYED; // server.dll is missed - remote servers only
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.background );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.banner );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.joinGame );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.createGame );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.gameInfo );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.refresh );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.done );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.hintMessage );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.gameList );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.msgBox );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.dlgMessage1 );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.dlgMessage2 );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.no );
UI_AddItem( &uiLanGame.menu, (void *)&uiLanGame.yes );
uiLanGame.refreshTime = uiStatic.realTime + 500; // delay before update 0.5 sec
}
/*
=================
UI_LanGame_Precache
=================
*/
void UI_LanGame_Precache( void )
{
PIC_Load( ART_BACKGROUND );
PIC_Load( ART_BANNER );
}
/*
=================
UI_LanGame_Menu
=================
*/
void UI_LanGame_Menu( void )
{
if ( gMenu.m_gameinfo.gamemode == GAME_SINGLEPLAYER_ONLY )
return;
// stop demos to allow network sockets to open
if ( gpGlobals->demoplayback && CVAR_GET_FLOAT( "cl_background" ))
{
uiStatic.m_iOldMenuDepth = uiStatic.menuDepth;
CLIENT_COMMAND( FALSE, "stop\n" );
uiStatic.m_fDemosPlayed = true;
}
UI_LanGame_Precache();
UI_LanGame_Init();
UI_PushMenu( &uiLanGame.menu );
}