From cbe38358134b3f6c2c4c4d2433ef8b3e595d23dd Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Fri, 18 Jan 2019 21:05:42 +0100 Subject: [PATCH] Menu: Implemented Custom Game menu. Beware that the engine doesn't switch mods fast enough so there will be caching issues. The widgets might also mess about because of I'm not killing any existing entities/widgets. Be warned. --- Source/Menu-FN/defs.h | 24 +++ Source/Menu-FN/entry.cpp | 23 ++- Source/Menu-FN/m_creategame.cpp | 2 +- Source/Menu-FN/m_customgame.cpp | 268 +++++++++++++++++++++++++++++ Source/Menu-FN/m_internetgames.cpp | 12 ++ Source/Menu-FN/m_langames.cpp | 12 ++ Source/Menu-FN/m_main.cpp | 45 +++-- Source/Menu-FN/m_newgame.cpp | 3 +- Source/Menu-FN/progs.src | 1 + 9 files changed, 377 insertions(+), 13 deletions(-) diff --git a/Source/Menu-FN/defs.h b/Source/Menu-FN/defs.h index 9ebecd2c..ff618fe3 100644 --- a/Source/Menu-FN/defs.h +++ b/Source/Menu-FN/defs.h @@ -39,6 +39,30 @@ typedef struct { void(float evtype, float scanx, float chary, float devid) m_input; } menupage_t; +typedef struct +{ + string game; + string gamedir; + string url_info; + string url_dl; + string version; + int size; + int svonly; + int cldll; + string type; + string hlversion; + int nomodels; + string mpentity; + string gamedll; + string startmap; + string trainingmap; +} gameinfo_t; + +var int gameinfo_current = -1; +int gameinfo_count; +gameinfo_t *games; +string(float id, float b) getgamedirinfo = #0; + int g_menupage; enum { diff --git a/Source/Menu-FN/entry.cpp b/Source/Menu-FN/entry.cpp index c50c297d..ca111b09 100644 --- a/Source/Menu-FN/entry.cpp +++ b/Source/Menu-FN/entry.cpp @@ -12,12 +12,17 @@ void m_init(void) 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", -1 ); + font_arial = loadfont( "label", "gfx/shell/arial.ttf", "14 11", -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 ); localcmd("plug_load ffmpeg\n"); + + /* TODO: Shove these into defaults.cfg instead of forcing them */ localcmd("con_textsize -12\n"); + localcmd("scr_conalpha 1\n"); + localcmd("cl_idlefps 0\n"); + shaderforname("logo_avi", "{\n{\nvideomap av:media/logo.avi\n}\n}"); for (int i = 0; i < g_bmp.length; i++) { @@ -29,12 +34,28 @@ void m_init(void) Strings_Init(); Colors_Init(); + games_init(); main_init(); } void m_shutdown(void) { + /*int i = 0; + for (i = 0; i < g_bmp.length; i++) { + freepic(g_bmp[i]); + } + entity e; + i = 1; + while ((e = edict_num(i)) != __NULL__) { + remove(e); + i++; + }*/ + + memfree(g_sprays); + memfree(g_models); + memfree(g_maps); + memfree(games); } void m_draw(vector screensize) diff --git a/Source/Menu-FN/m_creategame.cpp b/Source/Menu-FN/m_creategame.cpp index bcf8cfe7..872b2a0d 100644 --- a/Source/Menu-FN/m_creategame.cpp +++ b/Source/Menu-FN/m_creategame.cpp @@ -114,7 +114,7 @@ void menu_creategame_init(void) create_lbMaps = spawn(CListBox); create_lbMaps.SetPos(384,175); - create_lbMaps.SetSize(202,282); + create_lbMaps.SetSize(202-16,282); Widget_Add(fn_createshared, create_lbMaps); create_sbMaps = spawn(CScrollbar); diff --git a/Source/Menu-FN/m_customgame.cpp b/Source/Menu-FN/m_customgame.cpp index 0b90e9b2..df08a7ec 100644 --- a/Source/Menu-FN/m_customgame.cpp +++ b/Source/Menu-FN/m_customgame.cpp @@ -6,14 +6,282 @@ * ****/ +/* +game: The name of the mod +url_info: The mod's informational web site +url_dl: The ftp site from where the mod can be downloaded +version: The mod's version number +size: The size, in bytes, of the mod +svonly: “1” if the mod is a server only mod ( no client side content or code ), “0” otherwise +cldll: 1 if the mod requires a matching client.dll +type: If this mod is "multiplayer_only", then the single player buttons ( New Game/Hazard Course/Load game etc.) are disabled in the Half-Life launcher +hlversion: The version of Half-Life for which the mod was generated. Revisions to Half-Life will require updates by mod authors. +nomodels: Set to “1” if model bitmaps should not be shown in the Multiplayer | Customize menu of the Half-Life launcher +mpentity: When a user chooses to create a listen server from the interface, each BSP file in the maps\ folder for the mod is searched. The entity data for the BSP is scanned for the presence of the string identified by mpentity. For insance, in Half-Life, the string is "info_player_deathmatch" ( which is also the default if no string is specified ) +gamedll: The game DLL to load for running a server for this mod. +startmap: When a user chooses "New Game" for a single player mod, this is the map that is loaded. +trainingmap: When a user chooses "Hazard Course" for a single player mod, this is the map that is loaded. +*/ + +//string(string s) setwindowcaption = #0; + +void game_printinfo(int i) +{ + print("==================================\n"); + print(sprintf("GAME ID %i\n", i)); + print("==================================\n"); + print(sprintf("game: %s\n", games[i].game)); + print(sprintf("gamedir: %s\n", games[i].gamedir)); + print(sprintf("url_info: %s\n", games[i].url_info)); + print(sprintf("url_dl: %s\n", games[i].url_dl)); + print(sprintf("version: %s\n", games[i].version)); + print(sprintf("size: %i bytes\n", games[i].size)); + print(sprintf("svonly: %i\n", games[i].svonly)); + print(sprintf("cldll: %i\n", games[i].cldll)); + print(sprintf("type: %s\n", games[i].type)); + print(sprintf("hlversion: %s\n", games[i].hlversion)); + print(sprintf("nomodels: %i\n", games[i].nomodels)); + print(sprintf("mpentity: %s\n", games[i].mpentity)); + print(sprintf("gamedll: %s\n", games[i].gamedll)); + print(sprintf("startmap: %s\n", games[i].startmap)); + print(sprintf("trainingmap: %s\n", games[i].trainingmap)); + print("==================================\n"); +} + +void games_init(void) +{ + int gameidx; + float county; + string gamedirname; + string gamedescription; + gameinfo_count = 0; + + for (gameidx = 0; (gamedirname = getgamedirinfo(gameidx, 0)); gameidx++) { + gameinfo_count++; + } + + print(sprintf("[MENU] Scanned %i game directories.\n", gameinfo_count)); + + if (!gameinfo_count) { + print("^1FATAL ERROR: NO VALID GAME DIRECTORIES HAVE BEEN FOUND!\n"); + crash(); + return; + } + + games = memalloc(sizeof(gameinfo_t) * gameinfo_count); + + for (gameidx = 0; (gamedirname = getgamedirinfo(gameidx, 0)); gameidx++) { + gamedescription = getgamedirinfo(gameidx, 1); + county = tokenize(gamedescription); + + /* Fill in the defaults */ + games[gameidx].game = gamedirname; + games[gameidx].gamedir = gamedirname; + games[gameidx].url_info = ""; + games[gameidx].url_dl = ""; + games[gameidx].version = "1.0"; + games[gameidx].size = 0; + games[gameidx].svonly = 0; + games[gameidx].cldll = 1; + games[gameidx].type = ""; + games[gameidx].hlversion = "1110"; + games[gameidx].nomodels = 0; + games[gameidx].mpentity = "info_player_deathmatch"; + games[gameidx].gamedll = "progs.dat"; + games[gameidx].startmap = "c0a0"; + games[gameidx].trainingmap = "t0a0"; + + for ( int i = 0; i < county; i+=2 ) { + switch( argv(i) ) { + case "game": + games[gameidx].game = argv(i + 1); + print(sprintf("[GAME] Found %s (%s)\n", games[gameidx].game, gamedirname)); + break; + case "gamedir": + games[gameidx].gamedir = argv(i + 1); + break; + case "url_info": + games[gameidx].url_info = argv(i + 1); + break; + case "url_dl": + games[gameidx].url_dl = argv(i + 1); + break; + case "version": + games[gameidx].version = argv(i + 1); + break; + case "size": + games[gameidx].size = stof(argv(i + 1)); + break; + case "svonly": + games[gameidx].svonly = stof(argv(i + 1)); + break; + case "cldll": + games[gameidx].cldll = stof(argv(i + 1)); + break; + case "type": + games[gameidx].type = argv(i + 1); + break; + case "hlversion": + games[gameidx].hlversion = argv(i + 1); + break; + case "nomodels": + games[gameidx].nomodels = stof(argv(i + 1)); + break; + case "mpentity": + games[gameidx].mpentity = argv(i + 1); + break; + case "gamedll": + games[gameidx].gamedll = argv(i + 1); + break; + case "startmap": + games[gameidx].startmap = argv(i + 1); + break; + case "trainingmap": + case "trainmap": + games[gameidx].trainingmap = argv(i + 1); + break; + default: + break; + } + } + if (games[gameidx].gamedir == cvar_string("game")) { + gameinfo_current = gameidx; + } + game_printinfo(gameidx); + } + + if (gameinfo_current == -1) { + print("^1FATAL ERROR: NO MODINFO.TXT FOR RUNNING GAME DETECTED!\n"); + crash(); + return; + } else { + //cvar_set("fs_gamename", games[gameinfo_current].game); + print("[MENU] Found game we're running! Great success.\n"); + } +} + +CWidget fn_customgame; +CFrame customgame_frMods; +CModList customgame_lbMods; + +CMainButton customgame_btnActivate; +CMainButton customgame_btnInstall; +CMainButton customgame_btnVisit; +CMainButton customgame_btnRefresh; +CMainButton customgame_btnDeactivate; +CMainButton customgame_btnDone; + +void customgame_btnactivate_start(void) +{ + int nextgame = customgame_lbMods.GetSelected(); + if (!nextgame) { + return; + } + + gameinfo_current = nextgame; + localcmd(sprintf("gamedir \"%s\"\n", games[nextgame].gamedir)); + // TODO: Re-init important menu bits and bobs. + + m_shutdown(); + m_init(); +} +void customgame_btndeactivate_start(void) +{ + localcmd("gamedir \"\"\n"); + // TODO: Re-init important menu bits and bobs. + + m_shutdown(); + m_init(); +} + +void customgame_btndone_start(void) +{ + static void customgame_btndone_end(void) { + g_menupage = PAGE_MAIN; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(45,45,70,348); + header.SetStartEndSize(460,80,156,26); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_CUSTOM); + header.SetExecute(customgame_btndone_end); +} + void menu_customgame_init(void) { + fn_customgame = spawn(CWidget); + + customgame_btnActivate = spawn(CMainButton); + customgame_btnActivate.SetImage(BTN_ACTIVATE); + customgame_btnActivate.SetPos(15,140); + customgame_btnActivate.SetExecute(customgame_btnactivate_start); + Widget_Add(fn_customgame, customgame_btnActivate); + + customgame_btnInstall = spawn(CMainButton); + customgame_btnInstall.SetImage(BTN_INSTALL); + customgame_btnInstall.SetPos(15,172); + Widget_Add(fn_customgame, customgame_btnInstall); + + customgame_btnVisit = spawn(CMainButton); + customgame_btnVisit.SetImage(BTN_VISITWEB); + customgame_btnVisit.SetPos(15,204); + Widget_Add(fn_customgame, customgame_btnVisit); + + customgame_btnRefresh = spawn(CMainButton); + customgame_btnRefresh.SetImage(BTN_REFRESHLIST); + customgame_btnRefresh.SetPos(15,236); + Widget_Add(fn_customgame, customgame_btnRefresh); + + customgame_btnDeactivate = spawn(CMainButton); + customgame_btnDeactivate.SetImage(BTN_DEACTIVATE); + customgame_btnDeactivate.SetPos(15,300); + customgame_btnDeactivate.SetExecute(customgame_btndeactivate_start); + Widget_Add(fn_customgame, customgame_btnDeactivate); + + customgame_btnDone = spawn(CMainButton); + customgame_btnDone.SetImage(BTN_DONE); + customgame_btnDone.SetPos(15,332); + customgame_btnDone.SetExecute(customgame_btndone_start); + Widget_Add(fn_customgame, customgame_btnDone); + + customgame_frMods = spawn(CFrame); + customgame_frMods.SetPos(141,156); + customgame_frMods.SetSize(463,289); + Widget_Add(fn_customgame, customgame_frMods); + + customgame_lbMods = spawn(CModList); + customgame_lbMods.SetPos(144,159); + customgame_lbMods.SetSize(457,283); + Widget_Add(fn_customgame, customgame_lbMods); + + //customgame_lbMods.SetMax(gameinfo_count); } void menu_customgame_draw(void) { + drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_CUSTOM],[460,80], [1,1,1], 1.0f, 1); + Widget_Draw(fn_customgame); + + WLabel_Static(g_menuofs[0] + 155, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_TYPE], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 201, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_NAME], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 321, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_VERSION], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 371, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_SIZE], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 421, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_RATING], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 471, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_INSTALLED], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 521, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_SERVERS], 11, 11, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 571, g_menuofs[1] + 143, m_reslbl[IDS_MODLIST_PLAYERS], 11, 11, [1,1,1], + 1.0f, 0, font_arial); } void menu_customgame_input(float evtype, float scanx, float chary, float devid) { + Widget_Input(fn_customgame, evtype, scanx, chary, devid); } diff --git a/Source/Menu-FN/m_internetgames.cpp b/Source/Menu-FN/m_internetgames.cpp index b34cc184..6177f7f0 100644 --- a/Source/Menu-FN/m_internetgames.cpp +++ b/Source/Menu-FN/m_internetgames.cpp @@ -163,6 +163,18 @@ void menu_internetgames_draw(void) Widget_Draw(fn_inet); Master_ResortCache(); drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_INETGAMES],[460,80], [1,1,1], 1.0f, 1); + + /* Labels */ + WLabel_Static(g_menuofs[0] + 252, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_GAMESERVER], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 357, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_SPEED], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 407, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_MAP], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 476, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_GAME], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 552, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_PLAYERS], 10, 10, [1,1,1], + 1.0f, 0, font_arial); } void menu_internetgames_input(float evtype, float scanx, float chary, float devid) diff --git a/Source/Menu-FN/m_langames.cpp b/Source/Menu-FN/m_langames.cpp index d9544418..0f728782 100644 --- a/Source/Menu-FN/m_langames.cpp +++ b/Source/Menu-FN/m_langames.cpp @@ -133,6 +133,18 @@ void menu_langames_draw(void) Widget_Draw(fn_lan); Master_ResortCache(); drawpic([g_menuofs[0]+45,g_menuofs[1]+45], g_bmp[HEAD_LAN],[460,80], [1,1,1], 1.0f, 1); + + /* Labels */ + WLabel_Static(g_menuofs[0] + 282, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_GAMESERVER], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 377, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_SPEED], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 422, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_MAP], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 497, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_GAME], 10, 10, [1,1,1], + 1.0f, 0, font_arial); + WLabel_Static(g_menuofs[0] + 572, g_menuofs[1] + 128, m_reslbl[IDS_SERVER_PLAYERS], 10, 10, [1,1,1], + 1.0f, 0, font_arial); } void menu_langames_input(float evtype, float scanx, float chary, float devid) diff --git a/Source/Menu-FN/m_main.cpp b/Source/Menu-FN/m_main.cpp index df18267d..60a81705 100644 --- a/Source/Menu-FN/m_main.cpp +++ b/Source/Menu-FN/m_main.cpp @@ -61,6 +61,11 @@ void btn_newgame_start(void) header.SetHeader(HEAD_NEWGAME); header.SetExecute(btn_newgame_end); } +void btn_training(void) +{ + localcmd("maxplayers 1\n"); + localcmd(sprintf("map %s\n", games[gameinfo_current].trainingmap)); +} void btn_configuration_start(void) { static void btn_configuration_end(void) { @@ -87,12 +92,19 @@ void btn_multiplayer_start(void) header.SetHeader(HEAD_MULTI); header.SetExecute(btn_multiplayer_end); } - -void btn_training(void) +void btn_customgame_start(void) { - localcmd("maxplayers 1\nmap t0a0\n"); + static void btn_customgame_end(void) { + g_menupage = PAGE_CUSTOMGAME; + } + localsound("../media/launch_upmenu1.wav"); + header.SetStartEndPos(70,320,45,45); + header.SetStartEndSize(156,26,460,80); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_CUSTOM); + header.SetExecute(btn_customgame_end); } - void btn_quit(void) { main_quitdialog = TRUE; @@ -119,13 +131,17 @@ void menu_main_init(void) main_btnNewGame = spawn(CMainButton); main_btnNewGame.SetImage(BTN_NEWGAME); - main_btnNewGame.SetExecute(btn_newgame_start); + if (games[gameinfo_current].type != "multiplayer_only") { + main_btnNewGame.SetExecute(btn_newgame_start); + } main_btnNewGame.SetPos(70,208); Widget_Add(fn_main, main_btnNewGame); main_btnTraining = spawn(CMainButton); main_btnTraining.SetImage(BTN_TRAINING); - main_btnTraining.SetExecute(btn_training); + if (games[gameinfo_current].type != "multiplayer_only") { + main_btnTraining.SetExecute(btn_training); + } main_btnTraining.SetPos(70,236); Widget_Add(fn_main, main_btnTraining); @@ -137,17 +153,23 @@ void menu_main_init(void) main_btnLoadGame = spawn(CMainButton); main_btnLoadGame.SetImage(BTN_LOADGAME); + if (games[gameinfo_current].type != "multiplayer_only") { + // Loadgame disabled + } main_btnLoadGame.SetPos(70,292); Widget_Add(fn_main, main_btnLoadGame); main_btnMultiplayer = spawn(CMainButton); main_btnMultiplayer.SetImage(BTN_MULTIPLAYER); main_btnMultiplayer.SetPos(70,320); - main_btnMultiplayer.SetExecute(btn_multiplayer_start); + if (games[gameinfo_current].type != "singleplayer_only") { + main_btnMultiplayer.SetExecute(btn_multiplayer_start); + } Widget_Add(fn_main, main_btnMultiplayer); main_btnCustomGame = spawn(CMainButton); main_btnCustomGame.SetImage(BTN_CUSTOMGAME); + main_btnCustomGame.SetExecute(btn_customgame_start); main_btnCustomGame.SetPos(70,348); Widget_Add(fn_main, main_btnCustomGame); @@ -266,9 +288,12 @@ void menu_main_draw(void) WLabel_Static(235, 440, m_reslbl[IDS_MAIN_QUITHELP], 10, 10, col_help,1.0f, 0, font_label); } else { - drawpic([g_menuofs[0],g_menuofs[1] + 70], "logo_avi", - g_logosize, [1,1,1], 1.0f); - g_logosize = gecko_get_texture_extent("logo_avi"); + /* Don't even attempt to display the logo.avi otherwise */ + if (checkcommand("ffmpeg_videobitrate")) { + drawpic([g_menuofs[0],g_menuofs[1] + 70], "logo_avi", + g_logosize, [1,1,1], 1.0f); + g_logosize = gecko_get_texture_extent("logo_avi"); + } Widget_Draw(fn_main); WLabel_Static(235, 216, m_reslbl[IDS_MAIN_NEWGAMEHELP], 10, 10, diff --git a/Source/Menu-FN/m_newgame.cpp b/Source/Menu-FN/m_newgame.cpp index 94376c2b..43ea30e6 100644 --- a/Source/Menu-FN/m_newgame.cpp +++ b/Source/Menu-FN/m_newgame.cpp @@ -17,7 +17,8 @@ void ng_btneasy_start(void) { static void ng_btneasy_end(void) { g_menupage = PAGE_MAIN; - localcmd("maxplayers 1\nmap c0a0\n"); + localcmd("maxplayers 1\n"); + localcmd(sprintf("map %s\n", games[gameinfo_current].startmap)); } localsound("../media/launch_upmenu1.wav"); header.SetStartEndPos(45,45,70,208); diff --git a/Source/Menu-FN/progs.src b/Source/Menu-FN/progs.src index ec2d4bf4..c4265abb 100644 --- a/Source/Menu-FN/progs.src +++ b/Source/Menu-FN/progs.src @@ -27,6 +27,7 @@ w_listbox.cpp w_servers.cpp w_mainbutton.cpp w_modetab.cpp +w_modlist.cpp w_pagetab.cpp w_pictureswitch.cpp w_slider.cpp