From c813e49b5618bf43ccd7e5d385067c626b0ae9e3 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Wed, 1 Apr 2020 01:08:01 +0200 Subject: [PATCH] Menu: Lots of work done, like switching player models, sprays - IRC chat, custom game installs and listings. --- src/menu-fn/defs.h | 14 +- src/menu-fn/entry.cpp | 5 +- src/menu-fn/m_audio.cpp | 27 +++- src/menu-fn/m_chatrooms.cpp | 236 +++++++++++++++++++++++++++--- src/menu-fn/m_chatroomslist.cpp | 84 +++++++++++ src/menu-fn/m_creategame.cpp | 2 +- src/menu-fn/m_creategame_inet.cpp | 1 + src/menu-fn/m_customgame.cpp | 37 ++++- src/menu-fn/m_customize.cpp | 50 +++++-- src/menu-fn/m_internetgames.cpp | 1 + src/menu-fn/m_multiplayer.cpp | 26 ++++ src/menu-fn/menu.cpp | 1 + src/menu-fn/modserver.cpp | 204 ++++++++++++++++++++++++++ src/menu-fn/progs.src | 2 + src/menu-fn/w_mainbutton.cpp | 6 +- src/menu-fn/w_modlist.cpp | 23 +-- src/menu-fn/w_pictureswitch.cpp | 52 ++++++- src/menu-fn/w_textbox.cpp | 20 ++- src/server/valve/client.c | 4 + 19 files changed, 720 insertions(+), 75 deletions(-) create mode 100644 src/menu-fn/m_chatroomslist.cpp create mode 100644 src/menu-fn/modserver.cpp diff --git a/src/menu-fn/defs.h b/src/menu-fn/defs.h index 279b23ee..41e0e2c9 100644 --- a/src/menu-fn/defs.h +++ b/src/menu-fn/defs.h @@ -16,13 +16,13 @@ var int autocvar_menu_intro = TRUE; -#define KEY_UNKNOWN -1 -#define KEY_GAME 0 -#define KEY_MENU 2 -#define KEY_MENU_GRABBED 3 +#define KEY_UNKNOWN -1 +#define KEY_GAME 0 +#define KEY_MENU 2 +#define KEY_MENU_GRABBED 3 -#define TARGET_MENU 1 -#define TARGET_CLIENT 2 +#define TARGET_MENU 1 +#define TARGET_CLIENT 2 /* Basic Menu Globals */ int g_vidsize[2]; @@ -60,6 +60,7 @@ typedef struct string type; string hlversion; int nomodels; + int installed; string mpentity; string gamedll; string startmap; @@ -92,6 +93,7 @@ enum { PAGE_INTERNETGAMES, PAGE_ADDSERVER, PAGE_CHATROOMS, + PAGE_CHATROOMS_LIST, PAGE_CREATEGAME, PAGE_CREATEGAMEINET, PAGE_ADVANCEDMPOPTIONS, diff --git a/src/menu-fn/entry.cpp b/src/menu-fn/entry.cpp index 51088dcc..0d5e1930 100644 --- a/src/menu-fn/entry.cpp +++ b/src/menu-fn/entry.cpp @@ -59,9 +59,9 @@ void m_init(void) registercommand("menu_customgame"); font_console = loadfont( "font", "", "12", -1 ); font_label = loadfont( "label", "gfx/shell/mssansserif.ttf", "10 12 14", -1 ); - font_arial = loadfont( "label", "gfx/shell/arial.ttf", "14 11", -1 ); + font_arial = loadfont( "label", "gfx/shell/arial.ttf", "14 11 12", -1 ); font_label_b = loadfont( "label_b", "gfx/shell/arialbd.ttf", "14 12", -1 ); - font_label_p = loadfont( "label_p", "gfx/shell/arialbd.ttf", "16", -1 ); + font_label_p = loadfont( "label_p", "gfx/shell/arialbd.ttf", "16 21", -1 ); localcmd("plug_load ffmpeg\n"); @@ -74,6 +74,7 @@ void m_init(void) g_btnsize = drawgetimagesize(g_bmp[BTNS_MAIN]); g_btnofs = 26 / g_btnsize[1]; + precache_pic("gfx/shell/fragnet"); games_init(); main_init(); diff --git a/src/menu-fn/m_audio.cpp b/src/menu-fn/m_audio.cpp index 6fdd1081..099ec963 100644 --- a/src/menu-fn/m_audio.cpp +++ b/src/menu-fn/m_audio.cpp @@ -23,6 +23,11 @@ CCheckBox au_cxHQSound; CCheckBox au_cxA3DSound; CCheckBox au_cxEAXSound; +/* in the original WON menu, there is no music control */ +#ifndef ACCURATE +CSlider au_sldMusicVolume; +#endif + /* Button Callbacks */ void au_btndone_start(void) { @@ -45,9 +50,16 @@ void au_sldsuitvolume_changed(float val) { cvar_set("suitvolume", ftos(val)); } + +#ifndef ACCURATE +void au_sldmusicvolume_changed(float val) +{ + cvar_set("bgmvolume", ftos(val)); +} +#endif + void au_cxcdmusic_changed(float val) { - } void au_cxhqsound_changed(float val) { @@ -83,6 +95,14 @@ void menu_audio_init(void) au_sldSuitVolume.SetValue(cvar("suitvolume")); au_sldSuitVolume.SetCallback(au_sldsuitvolume_changed); Widget_Add(fn_audio, au_sldSuitVolume); + +#ifndef ACCURATE + au_sldMusicVolume = spawn(CSlider); + au_sldMusicVolume.SetPos(395,168); + au_sldMusicVolume.SetValue(cvar("bgmvolume")); + au_sldMusicVolume.SetCallback(au_sldmusicvolume_changed); + Widget_Add(fn_audio, au_sldMusicVolume); +#endif au_cxCDMusic = spawn(CCheckBox); au_cxCDMusic.SetPos(208,244); @@ -125,8 +145,13 @@ void menu_audio_draw(void) WLabel_Static(232, 347, m_reslbl[IDS_AUDIO_EAX], 12, 12, [0.75,0.75,0.75], 1.0f, 0, font_label_b); +#ifdef ACCURATE WField_Static(395, 133, m_reslbl[IDS_AUDIO_CDHINT], 169, 64, col_help, 1.0f, 1, font_label); +#else + WLabel_Static(395, 143, "Music volume:", 14, 14, [1,1,1], + 1.0f, 0, font_label_b); +#endif } void menu_audio_input(float evtype, float scanx, float chary, float devid) diff --git a/src/menu-fn/m_chatrooms.cpp b/src/menu-fn/m_chatrooms.cpp index 2eb4c0f0..3237ab99 100644 --- a/src/menu-fn/m_chatrooms.cpp +++ b/src/menu-fn/m_chatrooms.cpp @@ -14,51 +14,239 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +CFrame cr_frLog; +CFrame cr_frUsers; +CTextBox cr_tbInput; CWidget fn_chatrooms; -CMainButton cr_btnJoin; -CMainButton cr_btnCreateRoom; -CMainButton cr_btnCancel; +CMainButton cr_btnListRooms; +CMainButton cr_btnSearch; +CMainButton cr_btnServers; +CMainButton cr_btnDone; +CListBox cr_lbUsers; +CDialog cr_dgConnect; -void cr_btncancel_start(void) +typedef struct { - static void cr_btncancel_end(void) { + string cur_tab; + string show_tab; + int channel_grabbed; + float user_refresh; + float timer; +} ircsession_t; +ircsession_t g_irc; + +var string g_crIRCchannel; +var int g_iIRCActive; + +/* we've got a Internet servers button on here, so we require these */ +void() cr_btnservers_start; + +void cr_closeconnection(void) +{ + if (!g_iIRCActive) { + return; + } + /* how is this meant to work? neither do! */ + con_printf(g_irc.show_tab, "/clear\n"); + con_getset(g_irc.show_tab, "clear"); + localcmd("irc /disconnect irc.frag-net.com:6667\n"); + g_iIRCActive = FALSE; +} + +void cr_btndone_start(void) +{ + static void cr_btndone_end(void) { g_menupage = PAGE_MULTIPLAYER; } + cr_closeconnection(); localsound("../media/launch_dnmenu1.wav"); - header.SetStartEndPos(45,45,50,236); + header.SetStartEndPos(45,45,50,239); header.SetStartEndSize(460,80,156,26); header.m_lerp = 0.0f; header.m_visible = TRUE; - header.SetHeader(HEAD_MULTI); - header.SetExecute(cr_btncancel_end); + header.SetHeader(HEAD_ROOMS); + header.SetExecute(cr_btndone_end); +} + +void cr_btnlistrooms_start(void) +{ + static void cr_btnlistrooms_end(void) { + g_menupage = PAGE_CHATROOMS_LIST; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(30,70,45,45); + header.SetStartEndSize(156,26,460,80); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ROOMS); + header.SetExecute(cr_btnlistrooms_end); +} + +/* 'Done' button */ +void cr_btnservers_prepare(void) +{ + cr_closeconnection(); + cr_btnservers_start(); +} + +/* initial connect */ +void cr_makeconnection(void) +{ + localcmd("plug_load irc\n"); + localcmd(sprintf("seta irc_nick %.9s\n", cvar_string("name"))); + localcmd(sprintf("seta irc_altnick %.5s%.4d\n", cvar_string("name"), rint(random(1000,9999)))); + g_crIRCchannel = "#lobby"; + localcmd(sprintf("irc /open irc.frag-net.com:6667 %s\n", g_crIRCchannel)); +} + +/* when ENTER is pressed on the message box */ +void cr_input_enter(string text) +{ + localcmd(sprintf("irc /msg %s %s\n", g_crIRCchannel, text)); + cr_tbInput.SetText(""); } void menu_chatrooms_init(void) { fn_chatrooms = spawn(CWidget); - cr_btnJoin = spawn(CMainButton); - cr_btnJoin.SetImage(BTN_JOIN); - //cr_btnJoin.SetExecute(cr_btncancel_start); - cr_btnJoin.SetPos(50,140); - Widget_Add(fn_chatrooms, cr_btnJoin); + cr_btnListRooms = spawn(CMainButton); + cr_btnListRooms.SetImage(BTN_LISTROOMS); + cr_btnListRooms.SetExecute(cr_btnlistrooms_start); + cr_btnListRooms.SetPos(30,70); + Widget_Add(fn_chatrooms, cr_btnListRooms); - cr_btnCreateRoom = spawn(CMainButton); - cr_btnCreateRoom.SetImage(BTN_CREATEROOM); - //cr_btnCreateRoom.SetExecute(cr_btncancel_start); - cr_btnCreateRoom.SetPos(50,172); - Widget_Add(fn_chatrooms, cr_btnCreateRoom); + cr_btnSearch = spawn(CMainButton); + cr_btnSearch.SetImage(BTN_SEARCH); + //cr_btnSearch.SetExecute(cr_btncancel_start); + cr_btnSearch.SetPos(156,70); + Widget_Add(fn_chatrooms, cr_btnSearch); - cr_btnCancel = spawn(CMainButton); - cr_btnCancel.SetImage(BTN_CANCEL); - cr_btnCancel.SetExecute(cr_btncancel_start); - cr_btnCancel.SetPos(50,204); - Widget_Add(fn_chatrooms, cr_btnCancel); + cr_btnServers = spawn(CMainButton); + cr_btnServers.SetImage(BTN_INTERNET); + cr_btnServers.SetExecute(cr_btnservers_prepare); + cr_btnServers.SetPos(252,70); + Widget_Add(fn_chatrooms, cr_btnServers); + + cr_btnDone = spawn(CMainButton); + cr_btnDone.SetImage(BTN_DONE); + cr_btnDone.SetExecute(cr_btndone_start); + cr_btnDone.SetPos(408,70); + Widget_Add(fn_chatrooms, cr_btnDone); + + cr_tbInput = spawn(CTextBox); + cr_tbInput.SetPos(135,440); + cr_tbInput.SetText(""); + cr_tbInput.SetCallOnEnter(cr_input_enter); + cr_tbInput.SetLength(495); + Widget_Add(fn_chatrooms, cr_tbInput); + + cr_frLog = spawn(CFrame); + cr_frLog.SetPos(30,101); + cr_frLog.SetSize(472,337); + Widget_Add(fn_chatrooms, cr_frLog); + + cr_frUsers = spawn(CFrame); + cr_frUsers.SetPos(502,101); + cr_frUsers.SetSize(128,337); + Widget_Add(fn_chatrooms, cr_frUsers); + + cr_lbUsers = spawn(CListBox); + cr_lbUsers.SetPos(505,104); + cr_lbUsers.SetSize(122,331); + //cr_lbUsers.SetChanged(inet_lb_clicked); + Widget_Add(fn_chatrooms, cr_lbUsers); + cr_dgConnect = spawn(CDialog); +} + +string menu_chatrooms_gettopic(void) +{ + string t = cvar_string("irc_currenttopic"); + if (t == "") { + return "No topic"; + } else { + tokenizebyseparator(t, " - "); /* strip long descriptions */ + return argv(0); + } } void menu_chatrooms_draw(void) { + int tab_id; + string tmp; + + /* establish the connection */ + if (!g_iIRCActive) { + cr_makeconnection(); + g_iIRCActive = TRUE; + g_irc.timer = 10.0f; + } + Widget_Draw(fn_chatrooms); - drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_ROOMS],[460,80], [1,1,1], 1.0f, 1); + drawpic([g_menuofs[0]+550,g_menuofs[1]+10], "gfx/shell/fragnet",[80,80], [1,1,1], 1.0f, 0); + + /* we need to figure out which console buffer belongs to our chat. */ + g_irc.show_tab = g_irc.cur_tab; + for (tmp = "", tab_id = 0; tmp; tmp = con_getset(tmp, "next")) { + if (substring(tmp, 0, 3) == "IRC") { + con_getset( tmp, "hidden", "1" ); + string title = con_getset( tmp, "title" ); + } + } + if not (g_irc.channel_grabbed) + for (tmp = ""; tmp; tmp = con_getset(tmp, "next")) { + if (substring(tmp, 0, 3) == "IRC" && substring(tmp, -strlen(g_crIRCchannel), -1) == g_crIRCchannel) { + g_irc.show_tab = tmp; + g_irc.channel_grabbed = TRUE; + break; + } + } + if (!g_irc.show_tab) { + for (tmp = ""; tmp; tmp = con_getset(tmp, "next")) { + if (substring(tmp, 0, 3) == "IRC" && substring(tmp, -1, -1) == ":") { + g_irc.show_tab = tmp; + break; + } + } + } + g_irc.cur_tab = g_irc.show_tab; + + /* draw the irc-log buffer when ready */ + if (g_irc.show_tab) { + drawsetcliparea(g_menuofs[0] + 33, g_menuofs[1] + 104, 450,331); + con_draw(g_irc.show_tab, [g_menuofs[0] + 33, g_menuofs[1] + 104], [450,331], 12); + drawresetcliparea(); + } else { + /* connecting... dialog */ + cr_dgConnect.Draw(); + WField_Static(162, 180, m_reslbl[IDS_WON_LOGIN], 320, 260, + col_prompt_text, 1.0f, 2, font_label_p); + WField_Static(162, 280, sprintf(m_reslbl[IDS_CHAT_JOIN], g_crIRCchannel), 320, 260, + col_prompt_title, 1.0f, 2, font_label_p); + g_irc.timer -= frametime; + + if (g_irc.timer < 0.0) { + cr_btndone_start(); + } + } + + /* draw the labels */ + WLabel_Static(30, 38, m_reslbl[IDS_MULTI_CHATROOMCAPTION], 22, 22, [0.4,0.4,0.4], + 1.0f, 0, font_label_p); + WLabel_Static(155, 38, menu_chatrooms_gettopic(), 22, 22, [1,1,1], + 1.0f, 0, font_label_p); + WLabel_Static(30, 446, m_reslbl[IDS_CHAT_PROMPT], 12, 12, [1,1,1], + 1.0f, 0, font_arial); + + /* update the user list periodically */ + if (g_irc.user_refresh > time) { + return; + } + int c = tokenize(cvar_string("irc_currentusers")); + g_irc.user_refresh = time + 2.0f; + cr_lbUsers.Clear(); + for (int i = 0; i < c; i++) { + cr_lbUsers.AddEntry(argv(i)); + } } void menu_chatrooms_input(float evtype, float scanx, float chary, float devid) diff --git a/src/menu-fn/m_chatroomslist.cpp b/src/menu-fn/m_chatroomslist.cpp new file mode 100644 index 00000000..129ed256 --- /dev/null +++ b/src/menu-fn/m_chatroomslist.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +CWidget fn_chatroomslist; +CMainButton crl_btnJoin; +CMainButton crl_btnCreateRoom; +CMainButton crl_btnCancel; + +var string g_crIRCchannel; + +void crl_btnjoin_start(void) +{ + static void cr_btncancel_end(void) { + g_menupage = PAGE_CHATROOMS; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(30,70,30,70); + header.SetStartEndSize(460,80,156,26); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ROOMS); + header.SetExecute(cr_btncancel_end); +} + +void crl_btncancel_start(void) +{ + static void crl_btncancel_end(void) { + g_menupage = PAGE_CHATROOMS; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(30,70,30,70); + header.SetStartEndSize(460,80,156,26); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ROOMS); + header.SetExecute(crl_btncancel_end); +} + +void menu_chatroomslist_init(void) +{ + fn_chatroomslist = spawn(CWidget); + crl_btnJoin = spawn(CMainButton); + crl_btnJoin.SetImage(BTN_JOIN); + crl_btnJoin.SetExecute(crl_btnjoin_start); + crl_btnJoin.SetPos(50,140); + Widget_Add(fn_chatroomslist, crl_btnJoin); + + crl_btnCreateRoom = spawn(CMainButton); + crl_btnCreateRoom.SetImage(BTN_CREATEROOM); + //crl_btnCreateRoom.SetExecute(cr_btncancel_start); + crl_btnCreateRoom.SetPos(50,172); + Widget_Add(fn_chatroomslist, crl_btnCreateRoom); + + crl_btnCancel = spawn(CMainButton); + crl_btnCancel.SetImage(BTN_CANCEL); + crl_btnCancel.SetExecute(crl_btncancel_start); + crl_btnCancel.SetPos(50,204); + Widget_Add(fn_chatroomslist, crl_btnCancel); +} + +void menu_chatroomslist_draw(void) +{ + Widget_Draw(fn_chatroomslist); + drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_ROOMS],[460,80], [1,1,1], 1.0f, 1); + drawpic([g_menuofs[0]+550,g_menuofs[1]+10], "gfx/shell/fragnet",[80,80], [1,1,1], 1.0f, 0); +} + +void menu_chatroomslist_input(float evtype, float scanx, float chary, float devid) +{ + Widget_Input(fn_chatroomslist, evtype, scanx, chary, devid); +} diff --git a/src/menu-fn/m_creategame.cpp b/src/menu-fn/m_creategame.cpp index 6a24fde7..60f59ced 100644 --- a/src/menu-fn/m_creategame.cpp +++ b/src/menu-fn/m_creategame.cpp @@ -139,7 +139,7 @@ void menu_creategame_init(void) g_maps[i] = substring(search_getfilename(mapsearch, i), 5, -1); create_lbMaps.AddEntry(g_maps[i]); } - + create_sbMaps.SetMax(g_mapcount); search_end(mapsearch); } diff --git a/src/menu-fn/m_creategame_inet.cpp b/src/menu-fn/m_creategame_inet.cpp index 3b216866..c4e17b19 100644 --- a/src/menu-fn/m_creategame_inet.cpp +++ b/src/menu-fn/m_creategame_inet.cpp @@ -85,6 +85,7 @@ void menu_creategameinet_init(void) void menu_creategameinet_draw(void) { drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_CREATEGAME],[460,80], [1,1,1], 1.0f, 1); + drawpic([g_menuofs[0]+550,g_menuofs[1]+10], "gfx/shell/fragnet",[80,80], [1,1,1], 1.0f, 0); WLabel_Static(216, 143, m_reslbl[IDS_CREATESERVER_NAME], 14, 14, [1,1,1], 1.0f, 0, font_arial); diff --git a/src/menu-fn/m_customgame.cpp b/src/menu-fn/m_customgame.cpp index 3dc850b7..6189e20a 100644 --- a/src/menu-fn/m_customgame.cpp +++ b/src/menu-fn/m_customgame.cpp @@ -14,6 +14,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* local game/mod info parsing */ void games_set(int id) { gameinfo_current = id; @@ -61,6 +62,7 @@ void games_init(void) games[id].cldll = 1; games[id].hlversion = "1110"; games[id].svonly = 0; + games[id].installed = 1; for ( int i = 0; i < county; i+=2 ) { switch( argv(i) ) { @@ -129,10 +131,12 @@ void games_init(void) } } +/* the menu specific code */ CWidget fn_customgame; CFrame customgame_frMods; CModList customgame_lbMods; CScrollbar customgame_sbMods; +CDialog customgame_dlgWait; CMainButton customgame_btnActivate; CMainButton customgame_btnInstall; @@ -147,6 +151,7 @@ void customgame_btnactivate_start(void) games_set(nextgame); + /* some games/mods inherit other directories */ if (games[nextgame].fallback_dir) { localcmd(sprintf("gamedir \"%s;%s\"\n", games[nextgame].fallback_dir, games[nextgame].gamedir)); } else { @@ -154,10 +159,12 @@ void customgame_btnactivate_start(void) } localcmd("stopmusic\nsnd_restart\nwait\nvid_reload\nmenu_restart\nmenu_customgame\n"); - // TODO: Re-init important menu bits and bobs. cvar_init(); - //m_shutdown(); - //m_init(); +} +void customgame_btninstall_start(void) +{ + int gid = customgame_lbMods.GetSelected(); + localcmd(sprintf("fs_changegame %s\n", games[gid].url_dl)); } void customgame_btndeactivate_start(void) { @@ -185,9 +192,23 @@ void customgame_sbmods_changed(int val) customgame_lbMods.SetScroll(val); } +void customgame_lbmods_changed(void) +{ + int gid = customgame_lbMods.GetSelected(); + + if (games[gid].installed == TRUE) { + customgame_btnActivate.SetExecute(customgame_btnactivate_start); + customgame_btnInstall.SetExecute(__NULL__); + } else { + customgame_btnActivate.SetExecute(__NULL__); + customgame_btnInstall.SetExecute(customgame_btninstall_start); + } +} + void menu_customgame_init(void) { fn_customgame = spawn(CWidget); + customgame_dlgWait = spawn(CDialog); customgame_btnActivate = spawn(CMainButton); customgame_btnActivate.SetImage(BTN_ACTIVATE); @@ -208,6 +229,7 @@ void menu_customgame_init(void) customgame_btnRefresh = spawn(CMainButton); customgame_btnRefresh.SetImage(BTN_REFRESHLIST); customgame_btnRefresh.SetPos(15,236); + customgame_btnRefresh.SetExecute(ModServer_Refresh); Widget_Add(fn_customgame, customgame_btnRefresh); customgame_btnDeactivate = spawn(CMainButton); @@ -230,6 +252,7 @@ void menu_customgame_init(void) customgame_lbMods = spawn(CModList); customgame_lbMods.SetPos(144,159); customgame_lbMods.SetSize(457,283); + customgame_lbMods.SetChanged(customgame_lbmods_changed); Widget_Add(fn_customgame, customgame_lbMods); customgame_sbMods = spawn(CScrollbar); @@ -239,7 +262,6 @@ void menu_customgame_init(void) customgame_sbMods.SetCallback(customgame_sbmods_changed); customgame_sbMods.SetMax(gameinfo_count-1); /* don't show our current game */ Widget_Add(fn_customgame, customgame_sbMods); - } void menu_customgame_draw(void) @@ -263,6 +285,13 @@ void menu_customgame_draw(void) 1.0f, 0, font_arial); WLabel_Static(571, 143, m_reslbl[IDS_MODLIST_PLAYERS], 11, 11, [1,1,1], 1.0f, 0, font_arial); + + if (g_iModServerLoading) { + customgame_dlgWait.Draw(); + WField_Static(162, 180, m_reslbl[IDS_MODREQ_TITLE], 320, 260, + col_prompt_text, 1.0f, 2, font_label_p); + } + customgame_sbMods.SetMax(gameinfo_count-1); /* don't show our current game */ } void menu_customgame_input(float evtype, float scanx, float chary, float devid) diff --git a/src/menu-fn/m_customize.cpp b/src/menu-fn/m_customize.cpp index 56865ed3..fe4126ad 100644 --- a/src/menu-fn/m_customize.cpp +++ b/src/menu-fn/m_customize.cpp @@ -54,24 +54,40 @@ void cz_btnadvanced_start(void) header.SetExecute(cz_btnadvanced_end); } +void cz_cbModelChanged(void) +{ + string mdl = cz_psModel.GetPic(); + tokenizebyseparator(mdl, "/"); + localcmd(sprintf("seta _cl_playermodel %s\n", argv(2))); + localcmd(sprintf("setinfo model %s\n", argv(2))); +} + +void cz_cbSprayChanged(void) +{ + string mdl = cz_psSpray.GetPic(); + localcmd(sprintf("seta _cl_playerspray %s\n", mdl)); + localcmd(sprintf("setinfoblob spray %s\n", mdl)); +} + void menu_customize_init(void) { + /* scan and cache the sprays */ searchhandle searchy = search_begin("*.bmp", TRUE, TRUE); - g_sprays = memalloc(sizeof(string) * search_getsize(searchy)); - for (int i = 0; i < search_getsize(searchy); i++) { - precache_pic(search_getfilename(searchy, i)); + g_sprayscount = search_getsize(searchy); + g_sprays = memalloc(sizeof(string) * g_sprayscount); + for (int i = 0; i < g_sprayscount; i++) { g_sprays[i] = search_getfilename(searchy, i); - //g_sprays[i] = substring(search_getfilename(searchy, i), 0, -5); + precache_pic(g_sprays[i]); } search_end(searchy); - + + /* scan and cache the models */ searchy = search_begin("models/player/*/*.bmp", TRUE, TRUE); - g_models = memalloc(sizeof(string) * search_getsize(searchy)); - for (int i = 0; i < search_getsize(searchy); i++) { + g_modelcount = search_getsize(searchy); + g_models = memalloc(sizeof(string) * g_modelcount); + for (int i = 0; i < g_modelcount; i++) { g_models[i] = search_getfilename(searchy, i); - //tokenizebyseparator(search_getfilename(searchy, i),"/"); - //precache_pic(argv(2)); - //g_models[i] = argv(2); + precache_pic(g_models[i]); } search_end(searchy); @@ -98,10 +114,11 @@ void menu_customize_init(void) cz_psSpray.SetSize(99,124); cz_psSpray.SetPicSize(64,64); cz_psSpray.SetPicOffset(14,14); - cz_psSpray.SetMax(g_sprayscount); cz_psSpray.SetPics(g_sprays); - cz_psSpray.SetValueS("logo"); - //Widget_Add(fn_customize, cz_psSpray); + cz_psSpray.SetMax(g_sprayscount); + cz_psSpray.SetCallback(cz_cbSprayChanged); + cz_psSpray.SetValueS(cvar_string("_cl_playerspray")); + Widget_Add(fn_customize, cz_psSpray); cz_psModel = spawn(CPictureSwitch); cz_psModel.SetPos(410,160); @@ -109,8 +126,9 @@ void menu_customize_init(void) cz_psModel.SetPicSize(164,190); cz_psModel.SetPics(g_models); cz_psModel.SetMax(g_modelcount); - cz_psSpray.SetValueS("model"); - //Widget_Add(fn_customize, cz_psModel); + cz_psModel.SetCallback(cz_cbModelChanged); + cz_psModel.SetValueS(sprintf("models/player/%s/%s.bmp", cvar_string("_cl_playermodel"), cvar_string("_cl_playermodel"))); + Widget_Add(fn_customize, cz_psModel); } void menu_customize_draw(void) @@ -119,7 +137,7 @@ void menu_customize_draw(void) drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_CUSTOMIZE],[460,80], [1,1,1], 1.0f, 1); WLabel_Static(212, 140, m_reslbl[IDS_PLAYERINFO_NAME], 14, 14, [1,1,1], 1.0f, 0, font_arial); - WLabel_Static(410, 140, sprintf(m_reslbl[IDS_MODEL_NAME], "barney"), 14, 14, [1,1,1], + WLabel_Static(410, 140, sprintf(m_reslbl[IDS_MODEL_NAME], cvar_string("_cl_playermodel")), 14, 14, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(212, 203, m_reslbl[IDS_PROFILE_LOGO], 14, 14, [1,1,1], 1.0f, 0, font_arial); diff --git a/src/menu-fn/m_internetgames.cpp b/src/menu-fn/m_internetgames.cpp index 698e188f..3e5e11f0 100644 --- a/src/menu-fn/m_internetgames.cpp +++ b/src/menu-fn/m_internetgames.cpp @@ -243,6 +243,7 @@ void menu_internetgames_draw(void) Widget_Draw(fn_inet); resorthostcache(); drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_INETGAMES],[460,80], [1,1,1], 1.0f, 1); + drawpic([g_menuofs[0]+550,g_menuofs[1]+10], "gfx/shell/fragnet",[80,80], [1,1,1], 1.0f, 0); /* Labels */ WLabel_Static(252, 128, m_reslbl[IDS_SERVER_GAMESERVER], 10, 10, [1,1,1], diff --git a/src/menu-fn/m_multiplayer.cpp b/src/menu-fn/m_multiplayer.cpp index 9fd1d870..44193ec8 100644 --- a/src/menu-fn/m_multiplayer.cpp +++ b/src/menu-fn/m_multiplayer.cpp @@ -72,6 +72,32 @@ void mp_btninet_start(void) } } +/* this is from m_chatrooms.cpp */ +void cr_btnservers_start(void) +{ + static void cr_btnservers_end(void) { + g_menupage = PAGE_INTERNETGAMES; + } + + /* hack - jump to here so we draw the connection thing */ + g_menupage = PAGE_MULTIPLAYER; + cvar_set("sv_public", "1"); + localsound("../media/launch_upmenu1.wav"); + + if (g_connected == TRUE) { + header.SetStartEndPos(252,70,45,45); + header.SetStartEndSize(156,26,460,80); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_INETGAMES); + header.SetExecute(cr_btnservers_end); + } else { + Master_GetInternetList(); + g_connectstatus = CONNECT_INTERNET; + g_connecttimer = 8.0f; + } +} + void mp_btnlan_start(void) { static void mp_btnlan_end(void) { diff --git a/src/menu-fn/menu.cpp b/src/menu-fn/menu.cpp index eb8aaea8..fbc7dfca 100644 --- a/src/menu-fn/menu.cpp +++ b/src/menu-fn/menu.cpp @@ -32,6 +32,7 @@ menupage_t g_mpage[] = { { menu_internetgames_init, menu_internetgames_draw, menu_internetgames_input }, { menu_addserver_init, menu_addserver_draw, menu_addserver_input }, { menu_chatrooms_init, menu_chatrooms_draw, menu_chatrooms_input }, + { menu_chatroomslist_init, menu_chatroomslist_draw, menu_chatroomslist_input }, { menu_creategame_init, menu_creategame_draw, menu_creategame_input }, { menu_creategameinet_init, menu_creategameinet_draw, menu_creategameinet_input }, { menu_advancedmpoptions_init, menu_advancedmpoptions_draw, menu_advancedmpoptions_input }, diff --git a/src/menu-fn/modserver.cpp b/src/menu-fn/modserver.cpp new file mode 100644 index 00000000..1c24c91f --- /dev/null +++ b/src/menu-fn/modserver.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define MODSERVER_REQ_LIST 100 +#define MODSERVER_REQ_ITEM 101 + +#define ModServer_URI_Callback URI_Get_Callback + +var int g_iModServerLoading; +var int g_iModServerReqCount; + +void* +memrealloc(__variant *oldptr, int elementsize, int old_num, int new_num) +{ + void *n = memalloc(elementsize * new_num); + memcpy(n, oldptr, elementsize * min(old_num, new_num)); + memfree(oldptr); + return n; +} + +void +ModServer_Refresh(void) +{ + uri_get("http://www.frag-net.com/mods/_list.txt", MODSERVER_REQ_LIST); + g_iModServerLoading = TRUE; + g_iModServerReqCount = 0; +} + +void +ModServer_ParseList(string data) +{ + int c = 0; + int finalcount = 0; + c = tokenize(data); + + for (int i = 0; i < c; i++) { + int skip = 0; + string gamedir = argv(i); + + for (int x = 0; x < gameinfo_count; x++) { + /* skip mods we already have. */ + if (gamedir == games[x].gamedir) { + skip = 1; + break; + } + } + + if (skip) { + print(sprintf("^2ModServer_ParseList^7: Skipping %s\n", gamedir)); + continue; + } + + print(sprintf("^2ModServer_ParseList^7: Querying mod-data for %s\n", gamedir)); + uri_get(sprintf("http://www.frag-net.com/mods/%s.txt",gamedir), 101); + finalcount++; + } + + /* only count the ones that'll actually be queried */ + g_iModServerReqCount = finalcount; + + /* URI_GET never happens, so we can't count them down */ + if (g_iModServerReqCount == 0) { + g_iModServerLoading = FALSE; + } +} + +void +ModServer_ParseItem(string data) +{ + int id; + int c = tokenize(data); + + /* new id */ + id = gameinfo_count; + gameinfo_count++; + games = memrealloc(games, sizeof(gameinfo_t), id, gameinfo_count); + + if (!games) { + print("No more memory. Bye bye.\n"); + return; + } + + /* set up defaults */ + games[id].url_info = ""; + games[id].url_dl = ""; + games[id].version = "1.0"; + games[id].size = 0; + games[id].type = ""; + games[id].nomodels = 0; + games[id].mpentity = "info_player_deathmatch"; + games[id].gamedll = "progs.dat"; + games[id].startmap = "c0a0"; + games[id].trainingmap = "t0a0"; + games[id].cldll = 1; + games[id].hlversion = "1110"; + games[id].svonly = 0; + games[id].installed = 0; + + for (int i = 0; i < c; i+=2) { + switch( argv(i) ) { + case "game": + games[id].game = argv(i+1); + break; + case "gamedir": + games[id].gamedir = argv(i+1); + break; + case "fallback_dir": + games[id].fallback_dir = argv(i+1); + break; + case "url_info": + games[id].url_info = argv(i+1); + break; + case "url_dl": + games[id].url_dl = argv(i+1); + break; + case "version": + games[id].version = argv(i+1); + break; + case "size": + games[id].size = stof(argv(i+1)); + break; + case "svonly": + games[id].svonly = stof(argv(i+1)); + break; + case "cldll": + games[id].cldll = stof(argv(i+1)); + break; + case "type": + games[id].type = argv(i+1); + break; + case "hlversion": + games[id].hlversion = argv(i+1); + break; + case "nomodels": + games[id].nomodels = stof(argv(i+1)); + break; + case "mpentity": + games[id].mpentity = argv(i+1); + break; + case "gamedll": + games[id].gamedll = argv(i+1); + break; + case "startmap": + games[id].startmap = argv(i+1); + break; + case "trainingmap": + case "trainmap": + games[id].trainingmap = argv(i+1); + break; + default: + break; + } + } +} + +/* Called as an eventual result of the uri_get builtin. */ +void +ModServer_URI_Callback(float id, float code, string data) +{ + /* count our requests down */ + if (id == MODSERVER_REQ_ITEM) { + g_iModServerReqCount--; + + /* free the loading screen */ + if (g_iModServerReqCount <= 0) { + g_iModServerLoading = FALSE; + } + } + + /* unvailable */ + if (code && id == MODSERVER_REQ_LIST) { + print("^1ModServer_URI_Callback^7: Unable to retrieve list.\n"); + g_iModServerLoading = FALSE; + return; + } + if (code && id == MODSERVER_REQ_ITEM) { + print("^1ModServer_URI_Callback^7: Unable to retrieve mod entry.\n"); + return; + } + + switch (id) { + case MODSERVER_REQ_LIST: + ModServer_ParseList(data); + break; + case MODSERVER_REQ_ITEM: + ModServer_ParseItem(data); + break; + default: + print(sprintf("^1ModServer_URI_Callback^7: Unknown request id %d with code %d\n", id, code)); + } +} diff --git a/src/menu-fn/progs.src b/src/menu-fn/progs.src index dcc39d7c..2530acea 100644 --- a/src/menu-fn/progs.src +++ b/src/menu-fn/progs.src @@ -13,6 +13,7 @@ util.cpp colors.cpp master.cpp servers.cpp +modserver.cpp widgets.cpp w_checkbox.cpp @@ -39,6 +40,7 @@ m_advancedcustomize.cpp m_advancedmpoptions.cpp m_audio.cpp m_chatrooms.cpp +m_chatroomslist.cpp m_configuration.cpp m_contentcontrol.cpp m_controls.cpp diff --git a/src/menu-fn/w_mainbutton.cpp b/src/menu-fn/w_mainbutton.cpp index 65f4a191..b0b0ad23 100644 --- a/src/menu-fn/w_mainbutton.cpp +++ b/src/menu-fn/w_mainbutton.cpp @@ -143,11 +143,7 @@ void CMainButton::Draw(void) void CMainButton::Input(float type, float x, float y, float devid) { - if (Util_CheckMouse(m_x, m_y, m_length, 26) == TRUE) { - m_hover = TRUE; - } else { - m_hover = FALSE; - } + m_hover = Util_CheckMouse(m_x, m_y, m_length, 26); if (m_hover && type == IE_KEYDOWN && x == K_MOUSE1) { localsound("../media/launch_select2.wav"); diff --git a/src/menu-fn/w_modlist.cpp b/src/menu-fn/w_modlist.cpp index fe0f07d6..c3097e26 100644 --- a/src/menu-fn/w_modlist.cpp +++ b/src/menu-fn/w_modlist.cpp @@ -28,7 +28,7 @@ class CModList:CWidget int m_scroll; int m_selected; - //virtual void(int val) m_execute = 0; + virtual void() m_changed = 0; void() CModList; virtual void() Draw; @@ -73,10 +73,12 @@ void CModList::Draw(void) WLabel_Static(m_x + 2, pos + 3, sprintf("%.8s...",games[i].type), 11, 11, colo, 1.0f, 0, font_arial); } - + /* Game */ + drawsetcliparea(g_menuofs[0] + m_x + 57, g_menuofs[1] + pos + 3, 112,30); WLabel_Static(m_x + 57, pos + 3, games[i].game, 11, 11, colo, 1.0f, 0, font_arial); + drawresetcliparea(); /* URL */ WLabel_Static(m_x + 2, pos + 18, sprintf("Info: %s", games[i].url_info), 11, 11, ML_COL_4, 1.0f, 0, font_arial); @@ -91,7 +93,7 @@ void CModList::Draw(void) WLabel_Static(m_x + 277, pos + 3, "0.0", 11, 11, colo, 1.0f, 0, font_arial); /* Installed */ - WLabel_Static(m_x + 327, pos + 3, "Yes", 11, 11, ML_COL_3, + WLabel_Static(m_x + 327, pos + 3, (games[i].installed == 1) ? "Yes" : "No", 11, 11, ML_COL_3, 1.0f, 0, font_arial); /* Servers */ WLabel_Static(m_x + 377, pos + 3, "0", 11, 11, ML_COL_3, @@ -121,10 +123,7 @@ void CModList::Input(float type, float x, float y, float devid) if (Util_CheckMouse(pos[0], pos[1], m_size[0], 29)) { if (type == IE_KEYDOWN) { if (x == K_MOUSE1) { - m_selected = i; - /*if (m_execute) { - m_execute(i); - }*/ + SetSelected(i); break; } } @@ -144,14 +143,18 @@ void CModList::SetScroll(int i) m_scroll = i; } -/*void CModList::SetChanged(void(int val) func) +void CModList::SetChanged(void() func) { - m_execute = func; -}*/ + m_changed = func; +} void CModList::SetSelected(int i) { m_selected = i; + + if (m_changed) { + m_changed(); + } } int CModList::GetSelected(void) diff --git a/src/menu-fn/w_pictureswitch.cpp b/src/menu-fn/w_pictureswitch.cpp index 9dbfa040..cac58157 100644 --- a/src/menu-fn/w_pictureswitch.cpp +++ b/src/menu-fn/w_pictureswitch.cpp @@ -23,6 +23,10 @@ class CPictureSwitch:CWidget int m_picsize[2]; int m_picofs[2]; int m_size[2]; + + int m_hoverPrev; + int m_hoverNext; + virtual void() m_changed = 0; void() CPictureSwitch; virtual void() Draw; @@ -33,6 +37,8 @@ class CPictureSwitch:CWidget virtual void(int val) SetMax; virtual void(string val) SetValueS; virtual void(int w, int h) SetSize; + virtual void(void() vFunc) SetCallback; + virtual string() GetPic; }; void CPictureSwitch::CPictureSwitch(void) @@ -49,16 +55,36 @@ void CPictureSwitch::Draw(void) drawpic([m_picofs[0]+g_menuofs[0]+m_x+3,m_picofs[1]+g_menuofs[1]+m_y+3], m_pics[m_value], [m_picsize[0],m_picsize[1]], [1,1,1], 1.0f); - WLabel_Static(g_menuofs[0]+m_x+3, g_menuofs[1]+m_y+m_size[1]-16, m_reslbl[IDS_PREVIOUS], 12, 12, [1,1,1], + WLabel_Static(m_x+3, m_y+m_size[1]-16, m_reslbl[IDS_PREVIOUS], 12, 12, [1,1,1], 1.0f, 0, font_arial); - WLabel_StaticR(g_menuofs[0]+m_x+m_size[0]-4, - g_menuofs[1]+m_y+m_size[1]-16, m_reslbl[IDS_NEXT], 12, 12, + WLabel_StaticR(m_x+m_size[0]-4, + m_y+m_size[1]-16, m_reslbl[IDS_NEXT], 12, 12, [1,1,1],1.0f, 0, font_arial); } void CPictureSwitch::Input(float type, float x, float y, float devid) { - + int clickPrev, clickNext; + m_hoverPrev = Util_CheckMouse(m_x+3, m_y+m_size[1]-16, m_size[0]/2, 12); + m_hoverNext = Util_CheckMouse(m_x+m_size[0]-4-(m_size[0]/2), m_y+m_size[1]-16, m_size[0]/2, 12); + + if (m_hoverPrev && type == IE_KEYDOWN && x == K_MOUSE1) { + localsound("../media/launch_select2.wav"); + m_value--; + m_value = bound(0, m_value, m_max-1); + + if (m_changed) { + m_changed(); + } + } else if (m_hoverNext && type == IE_KEYDOWN && x == K_MOUSE1) { + localsound("../media/launch_select2.wav"); + m_value++; + m_value = bound(0, m_value, m_max-1); + + if (m_changed) { + m_changed(); + } + } } void CPictureSwitch::SetPics(string *m) @@ -69,6 +95,10 @@ void CPictureSwitch::SetPics(string *m) void CPictureSwitch::SetValue(int val) { m_value = val; + + if (m_changed) { + m_changed(); + } } void CPictureSwitch::SetMax(int val) @@ -83,6 +113,10 @@ void CPictureSwitch::SetValueS(string val) m_value = i; } } + + if (m_changed) { + m_changed(); + } } void CPictureSwitch::SetSize(int w, int h) @@ -102,3 +136,13 @@ void CPictureSwitch::SetPicOffset(int w, int h) m_picofs[0] = w; m_picofs[1] = h; } + +void CPictureSwitch::SetCallback(void() vFunc) +{ + m_changed = vFunc; +} + +string CPictureSwitch::GetPic(void) +{ + return m_pics[m_value]; +} diff --git a/src/menu-fn/w_textbox.cpp b/src/menu-fn/w_textbox.cpp index 70610488..b56048d3 100644 --- a/src/menu-fn/w_textbox.cpp +++ b/src/menu-fn/w_textbox.cpp @@ -27,11 +27,14 @@ class CTextBox:CWidget string m_text; int m_length; int m_flags; + virtual void(string) m_onEnter = 0; void() CTextBox; virtual void() Draw; - virtual void(float type, float x, float y, float devid) Input; - virtual void(string txt) SetText; + virtual void(float, float, float, float) Input; + virtual void(void(string) vFunc) SetCallOnEnter; + virtual void(string) SetText; + virtual void(int) SetLength; }; void CTextBox::CTextBox(void) @@ -79,6 +82,9 @@ void CTextBox::Input(float type, float x, float y, float devid) } break; case K_ENTER: + if (m_onEnter) { + m_onEnter(m_text); + } break; default: if (m_flags & TEXTBOX_FOCUS) { @@ -97,7 +103,17 @@ void CTextBox::Input(float type, float x, float y, float devid) } } +void CTextBox::SetCallOnEnter(void(string) vFunc) +{ + m_onEnter = vFunc; +} + void CTextBox::SetText(string txt) { m_text = txt; } + +void CTextBox::SetLength(int len) +{ + m_length = len; +} diff --git a/src/server/valve/client.c b/src/server/valve/client.c index b91ea7ca..a1e8c973 100644 --- a/src/server/valve/client.c +++ b/src/server/valve/client.c @@ -13,6 +13,7 @@ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +var int autocvar_sv_playerkeepalive = TRUE; void Game_ClientConnect(void) @@ -68,6 +69,9 @@ Game_PlayerPostThink(player pl) { Animation_PlayerUpdate(); + if (autocvar_sv_playerkeepalive) + pl.SendFlags |= PLAYER_KEEPALIVE; + if (pl.old_modelindex != pl.modelindex) pl.SendFlags |= PLAYER_MODELINDEX;