nuclide/Source/Menu/MenuMultiplayer.c
eukara 794b08d64c Added a hostname field to the menu
Fixed that a dropped C4 Bomb could not be picked up again
2017-11-17 15:45:48 -06:00

368 lines
No EOL
12 KiB
C
Executable file

/*
FreeCS Project
Copyright (C) 2016, 2017 Marco "eukara" Hladik
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.
*/
// Server fields!
float fldName;
float fldAddress;
float fldPing;
float fldPlayers;
float fldMaxplayers;
float fldMap;
float fldTimelimit;
float fldFraglimit;
float fServerClickTime;
/*
=================
Menu_Multiplayer_Connect
Connect to a specific ServerID from the hostcache
=================
*/
void Menu_Multiplayer_Connect( int iServerID ) {
// Filter dead entries
if ( gethostcachenumber( fldMaxplayers, iServerID ) <= 0 ) {
return;
}
// Connect as long as a real server is actually selected
if ( iServerID >= 0 ) {
localcmd( sprintf( "connect %s\n", gethostcachestring( fldAddress, iServerID ) ) );
m_hide();
}
}
/*
=================
Menu_Multiplayer_Find_Item
Draw a single server item from the hostcache
=================
*/
void Menu_Multiplayer_Find_Item( vector vPosition, int i, __inout int iSelected ) {
float fItemAlpha = 1.0f;
vPosition += vMenuOffset;
if ( Menu_InputCheckMouse( [ vPosition_x, vPosition_y ], [ 397, 8 ] ) == TRUE ) {
if ( fMouseClick == TRUE ) {
if ( iSelected != i ) {
iSelected = i;
fInputKeyCode = 0;
fMouseClick = FALSE;
fServerClickTime = time + 0.2;
} else {
if ( fServerClickTime > time ) {
Menu_Multiplayer_Connect( i );
}
iSelected = -2;
fInputKeyCode = 0;
fMouseClick = FALSE;
}
}
} else {
fItemAlpha = 0.8;
}
if ( iSelected == i ) {
drawfill( [ vPosition_x, vPosition_y - 1 ], [ 397, 10 ], '1 1 1', 0.5, 2 );
drawstring( [vPosition_x + 8, vPosition_y], sprintf( "%.25s", gethostcachestring( fldName, i ) ), '8 8 0', '1 1 1', 1.0f, FALSE );
drawstring( [vPosition_x + 218, vPosition_y], sprintf( "%.10s", gethostcachestring( fldMap, i ) ), '8 8 0', '1 1 1', 1.0f, FALSE );
drawstring( [vPosition_x + 298, vPosition_y], sprintf( "%d/%d", gethostcachenumber( fldPlayers, i ), gethostcachenumber( fldMaxplayers, i ) ), '8 8 0', '1 1 1', 1.0f, FALSE );
drawstring( [vPosition_x + 362, vPosition_y], sprintf( "%.3s", ftos( gethostcachenumber( fldPing, i ) ) ), '8 8 0', '1 1 1', 1.0f, FALSE );
} else {
drawstring( [vPosition_x + 8, vPosition_y], sprintf( "^3%.25s", gethostcachestring( fldName, i ) ), '8 8 0', '1 1 1', fItemAlpha, FALSE );
drawstring( [vPosition_x + 218, vPosition_y], sprintf( "%.10s", gethostcachestring( fldMap, i ) ), '8 8 0', '1 1 1', fItemAlpha, FALSE );
drawstring( [vPosition_x + 298, vPosition_y], sprintf( "%d/%d", gethostcachenumber( fldPlayers, i ), gethostcachenumber( fldMaxplayers, i ) ), '8 8 0', '1 1 1', fItemAlpha, FALSE );
drawstring( [vPosition_x + 362, vPosition_y], sprintf( "%.3s", ftos( gethostcachenumber( fldPing, i ) ) ), '8 8 0', '1 1 1', fItemAlpha, FALSE );
}
}
/*
=================
Menu_Multiplayer
First mulitplayer screen with the server browser
=================
*/
void Menu_Multiplayer( void ) {
static int iSelectedServer = -1;
static int iScrollServer;
static int iServersTotal;
static void Multiplayer_ButtonJoin( void ) {
if ( iSelectedServer >= 0 ) {
localcmd( sprintf( "connect %s\n", gethostcachestring( fldAddress, iSelectedServer ) ) );
m_hide();
}
}
static void Multiplayer_ButtonCreate( void ) {
iMenu = MENU_MULTIPLAYER_CREATE;
}
static void Multiplayer_ButtonRefresh( void ) {
refreshhostcache();
resorthostcache();
}
static void Multiplayer_ButtonDone( void ) {
iMenu = MENU_MAIN;
}
static void Multiplayer_ButtonIRC( void ) {
iMenu = MENU_MULTIPLAYER_IRC;
}
// Initialize it on the first run
if ( iSelectedServer == -1 ) {
//clear the filter
resethostcachemasks();
//sethostcachemaskstring( 0, gethostcacheindexforkey( "gamedir" ), "freecs", SLIST_TEST_EQUAL );
sethostcachesort( gethostcacheindexforkey( "ping" ), FALSE );
refreshhostcache();
iSelectedServer = -2;
}
resorthostcache();
fldName = gethostcacheindexforkey("name");
fldAddress = gethostcacheindexforkey("cname");
fldPing = gethostcacheindexforkey("ping");
fldPlayers = gethostcacheindexforkey("numhumans");
fldMaxplayers = gethostcacheindexforkey("maxplayers");
fldMap = gethostcacheindexforkey("map");
fldTimelimit = gethostcacheindexforkey("timelimit");
fldFraglimit = gethostcacheindexforkey("fraglimit");
iServersTotal = gethostcachevalue( SLIST_HOSTCACHEVIEWCOUNT );
Menu_SetClipArea( '32 148', '164 192' );
Object_Button( '32 148', BTN_JOINGAME, Multiplayer_ButtonJoin, fButtonAlpha[0] );
Object_Button( '32 180', BTN_CREATE, Multiplayer_ButtonCreate, fButtonAlpha[1] );
Object_Button( '32 212', BTN_GAMEINFO, __NULL__, fButtonAlpha[2] );
Object_Button( '32 244', BTN_REFRESHLIST, Multiplayer_ButtonRefresh, fButtonAlpha[3] );
if ( checkcommand( "irc" ) ) {
Object_Button( '32 276', BTN_IRCCHAT, Multiplayer_ButtonIRC, fButtonAlpha[4] );
}
Object_Button( '32 308', BTN_DONE, Multiplayer_ButtonDone, fButtonAlpha[5] );
Menu_ResetClipArea();
Object_Frame( '196 140', '404 308' );
Object_Scrollbar( '604 140', 308, iScrollServer );
Object_Label( '208 124', _("MP_GAME"), '8 8' );
Object_Label( '418 124', _("MP_MAP"), '8 8' );
Object_Label( '498 124', _("MP_PLAYERS"), '8 8' );
Object_Label( '562 124', _("MP_PING"), '8 8' );
Menu_SetClipArea( '196 141', '404 306' );
vector vListPos = '200 145';
vListPos_y -= fabs( ( ( iServersTotal - 8 ) * 10 ) * ( iScrollServer / 308 ) );
for ( int i = 0; i < iServersTotal; i++ ) {
Menu_Multiplayer_Find_Item( vListPos, i, iSelectedServer );
vListPos_y += 10;
}
Menu_ResetClipArea();
}
/*
=================
Menu_Multiplayer_Create
Server creation menu screen
=================
*/
void Menu_Multiplayer_Create( void ) {
static int iSelectedMap;
static int iScrollMap;
static int iFirst = 1;
static string strHostname;
static void Create_ListMap( vector vPosition, int iIndex ) {
float fAlpha = 0.8;
vPosition += vMenuOffset;
if ( iScrollbarHold == FALSE ) {
if ( Menu_InputCheckMouse( vPosition, '182 10' ) == TRUE ) {
if ( fMouseClick == TRUE ) {
iSelectedMap = iIndex;
fMouseClick = FALSE;
}
fAlpha = 1.0f;
}
}
if ( iSelectedMap == iIndex ) {
drawfill( [ vPosition_x, vPosition_y - 1 ], [ 182, 10 ], '1 1 1', 0.5, 2 );
drawstring( vPosition, sMapList[ iIndex ], '8 8', '1 1 1', 1.0f, 0 );
} else {
drawstring( vPosition, sMapList[ iIndex ], '8 8', '0.9 0.9 0.9', fAlpha, 0 );
}
}
static void Create_ButtonAdvanced( void ) {
// Advanced options
iMenu = MENU_MULTIPLAYER_OPTIONS;
}
static void Create_ButtonOK( void ) {
// Apply the configurations
if ( strHostname != __NULL__ ) {
localcmd( sprintf( "hostname %s\n", strHostname ) );
} else {
strHostname = cvar_string( "hostname" );
}
// Start server
localcmd( sprintf( "map %s\n", sMapList[ iSelectedMap ] ) );
}
static void Create_ButtonCancel( void ) {
iMenu = MENU_MULTIPLAYER;
}
if ( iFirst == 1 ) {
strHostname = cvar_string( "hostname" );
iFirst = 0;
}
Object_Button( '32 148', BTN_ADVOPTIONS, Create_ButtonAdvanced, fButtonAlpha[0] );
Object_Button( '32 180', BTN_OK, Create_ButtonOK, fButtonAlpha[1] );
Object_Button( '32 212', BTN_CANCEL, Create_ButtonCancel, fButtonAlpha[2] );
// Options
Object_Label( '196 148', _("SERVER_NAME"), '8 8' );
Object_Textfield( '196 160', strHostname, 20 );
// Map list
Object_Label( '384 148', _("MP_MAPS"), '8 8' );
Object_Frame( '384 164', '190 288' );
Object_Scrollbar( '576 164', 288, iScrollMap );
// Maplist
vector vListPos = '392 172';
Menu_SetClipArea( '386 166', '188 286' );
vListPos_y -= fabs( ( ( iMapCount - 21 ) * 10 ) * ( iScrollMap / 288 ) );
for ( int i = 0; i < iMapCount; i++ ) {
Create_ListMap( vListPos, i );
vListPos_y += 10;
}
Menu_ResetClipArea();
}
void Menu_Multiplayer_IRC( void ) {
static int iIRCInit = FALSE;
static string currenttab;
string showtab;
static string s; //static to access it in nested functions.
static void IRC_ButtonDone( void ) {
iMenu = MENU_MULTIPLAYER;
}
static void IRC_ButtonSelect(void) {
if (currenttab)
con_input(currenttab, IE_FOCUS, 0/*mouse focus*/, 0/*key focus*/, 0);
if (s)
{
currenttab = s;
con_input(currenttab, IE_FOCUS, 1/*mouse focus*/, 1/*key focus*/, 0);
}
}
if ( iIRCInit == FALSE ) {
print( "[IRC] Connecting to #freecs...\n" );
localcmd("/irc /connect irc.freenode.org #freecs\n");
iIRCInit = TRUE;
}
int iTabIdx;
vector vTabPos = '196 140';
for (s = "", iTabIdx = 0; s; s = con_getset(s, "next"))
{
if (substring(s, 0, 3) == "IRC")
{
con_getset( s, "hidden", "1" ); //Hide all IRC consoles. We're evil like that.
string title = con_getset( s, "title" );
iTabIdx++;
if (fButtonAlpha[iTabIdx] < 0.5)
fButtonAlpha[iTabIdx] = 0.5;
Object_TextButton( vTabPos, title, IRC_ButtonSelect, fButtonAlpha[iTabIdx] );
vTabPos_x += stringwidth(title, TRUE, '8 8') + 8;
}
}
//TODO: scroll tabs.
//TODO: add a close button
//TODO: make it friendly when in-game.
showtab = currenttab;
if not (showtab) //the channel we're trying to target
for (s = ""; s; s = con_getset(s, "next"))
{ //try to find our target channel
if (substring(s, 0, 3) == "IRC" && substring(s, -8, -1) == ":#freecs")
{
showtab = s;
break;
}
}
if (!showtab) //the server-messages channel. used more as a loading screen than anything else.
for (s = ""; s; s = con_getset(s, "next"))
{
if (substring(s, 0, 3) == "IRC" && substring(s, -1, -1) == ":")
{
showtab = s;
break;
}
}
//TODO: propagate input events to the currenttab.
if (currenttab)
{
if (Menu_InputCheckMouse( vMenuOffset + '196 148', '404 308' ))
{
con_input(currenttab, IE_MOUSEABS, vMousePos_x, vMousePos_y, 0);
if (fMouseClick)
{
con_input(currenttab, IE_KEYDOWN, K_MOUSE1, 0, 0);
con_input(currenttab, IE_KEYUP, K_MOUSE1, 0, 0);
}
con_input(currenttab, IE_FOCUS, 1/*mouse focus*/, 1/*key focus*/, 0);
}
else
con_input(currenttab, IE_FOCUS, 0/*mouse focus*/, 1/*key focus*/, 0);
//this is hideous
//BUG BUG BUG FIXME: The engine attempts to restrict con_input inputs.
//as a result, it can only be called inside CSQC_Input_Event (or menuqc equivelents)
//note that if you wish to handle IME strings then you should be doing that anyway.
if (fInputKeyCode != K_MOUSE1 && (fInputKeyCode || fInputKeyASCII))
{
//print(sprintf("Sending input: %f %f %c\n", fInputKeyCode, fInputKeyASCII, fInputKeyASCII));
con_input(currenttab, IE_KEYDOWN, fInputKeyCode, fInputKeyASCII, 0);
con_input(currenttab, IE_KEYUP, fInputKeyCode, fInputKeyASCII, 0);
fInputKeyCode = 0;
fInputKeyASCII = 0;
}
}
if (showtab)
con_draw( showtab, vMenuOffset + '196 148', '404 308', 8 );
else
Object_Label( '196 148', _("No IRC Output"), '8 8' );
Object_Button( '32 308', BTN_DONE, IRC_ButtonDone, fButtonAlpha[0] );
}