/* * Copyright (c) 2016-2022 Vera Visions LLC. * * 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. */ /* the menu specific variables */ #ifndef WEBMENU CWidget fn_customgame; CFrame customgame_frMods; CModList customgame_lbMods; CScrollbar customgame_sbMods; CDialog customgame_dlgWait; CMainButton customgame_btnActivate; CMainButton customgame_btnInstall; CMainButton customgame_btnVisit; CMainButton customgame_btnRefresh; CMainButton customgame_btnDeactivate; CMainButton customgame_btnDone; int g_iModInstallCache; string g_strModInstallCache; /* get installing id */ void game_getinstallcache(void) { int ret; filestream fs_cache; ret = 0; fs_cache = fopen("mcache.dat", FILE_READ); if (fs_cache >= 0) { g_iModInstallCache = (int)stof(fgets(fs_cache)); g_strModInstallCache = fgets(fs_cache); fclose(fs_cache); } else { g_iModInstallCache = -1; g_strModInstallCache = ""; } print(sprintf("id: %i, name: %s\n", ret, g_strModInstallCache)); } /* write installing id */ void game_writeinstallcache(int id, string gamedir) { filestream fs_cache; fs_cache = fopen("mcache.dat", FILE_WRITE); g_iModInstallCache = id; g_strModInstallCache = gamedir; if (fs_cache >= 0) { fputs(fs_cache, sprintf("%i\n",id)); fputs(fs_cache, gamedir); fclose(fs_cache); } } int game_getpackageid(string pkgname) { string f; for (int i = 0; (getpackagemanagerinfo(i, GPMI_NAME)); i++) { string name; name = getpackagemanagerinfo(i, GPMI_NAME); /* Spike started randomly putting version numbers into package names */ f = sprintf("%s=%s", pkgname, getpackagemanagerinfo(i, GPMI_VERSION)); if (name == f) { return i; } } /* no package id whatsoever */ return (-1); } /* return 1 if any of the packages are pending, installing, or corrupt */ int game_updatesavailable(void) { /* look for the valid packages in the gameinfo pkgname */ int pkgcount = tokenize(games[gameinfo_current].pkgname); for (int i = 0i; i < pkgcount; i++) { int id = game_getpackageid(argv(i)); string status = getpackagemanagerinfo(id, GPMI_INSTALLED); if (id == -1) continue; switch (status) { case "": if (updates[id].installed == "") { return (1); } else if (updates[id].installed == "pending") { return (1); } break; case "pending": return (1); break; case "enabled": break; case "present": return (1); break; case "corrupt": return (1); break; default: /* we're currently installing stuff */ return (1); break; } } /* everything is installed */ return (0); } int game_updateinstallcount(void) { int count = 0; /* always return something positive when no packages are defined */ if (games[gameinfo_current].pkgname == "") { return (1); } /* look for the valid packages in the gameinfo pkgname */ int pkgcount = tokenize(games[gameinfo_current].pkgname); for (int i = 0i; i < pkgcount; i++) { int id = game_getpackageid(argv(i)); string status = getpackagemanagerinfo(id, GPMI_INSTALLED); switch (status) { case "": break; case "pending": break; case "enabled": count++; break; case "present": count++; break; case "corrupt": count++; break; default: /* we're currently installing stuff */ break; } } /* everything is installed */ return count; } #endif /* local game/mod info parsing */ void games_set(int id) { gameinfo_current = id; setwindowcaption(games[id].game); cvar_set("com_fullgamename", games[id].game); } #ifndef WEBMENU void customgame_liblist_parse(int id, string strKey, string strValue) { switch(strKey) { case "game": games[id].game = strValue; break; case "gamedir": games[id].gamedir = strValue; break; case "fallback_dir": games[id].fallback_dir = strValue; break; case "url_info": games[id].url_info = strValue; break; case "url_dl": games[id].url_dl = strValue; break; case "version": games[id].version = strValue; break; case "size": games[id].size = (int)stof(strValue); break; case "svonly": games[id].svonly = (int)stof(strValue); break; case "cldll": games[id].cldll = (int)stof(strValue); break; case "type": switch (strtolower(strValue)) { case "multiplayer_only": case "multiplayer only": games[id].type = "Multiplayer"; break; case "singleplayer_only": case "singleplayer only": games[id].type = "Singleplayer"; break; /* this... kind of sucks, but some games (gearbox) never updated * their liblist to reflect that they do multiplayer */ case "sp": case "single": case "singleplayer": case "mp": case "multi": case "multiplayer": default: games[id].type = "Both"; } break; case "minversion": case "hlversion": games[id].hlversion = strValue; break; case "nomodels": games[id].nomodels = (int)stof(strValue); break; case "nosprays": games[id].nosprays = (int)stof(strValue); break; case "mpentity": games[id].mpentity = strValue; break; case "gamedll": games[id].gamedll = strValue; break; case "startmap": games[id].startmap = strcat("map ", strValue, "\n"); break; case "trainingmap": games[id].trainingmap = strcat("map ", strValue, "\n"); break; /* newly added with Nuclide */ case "pkgname": games[id].pkgname = strValue; games[id].pkgid = game_getpackageid(games[id].pkgname); break; case "pkgfile": games[id].pkgfile = strValue; break; case "chatroom": games[id].chatroom = strValue; break; case "readme": games[id].readme = strValue; break; case "menumap": games[id].menumap = strValue; break; case "introvideo": games[id].introvideo = strValue; break; case "steambg": games[id].steambg = (int)stof(strValue); break; case "base_dir": games[id].base_dir = strValue; break; default: break; } } /* looks for a single find inside a gamedir, including its pk3s and returns * a valid filehandle if it is found */ filestream games_find_in_gamedir(string filename, string gamedirname) { searchhandle sh; searchhandle gsh; searchhandle psh; filestream fh; /* first let's see if we've got a liblist.gam just floating inside the gamedir */ gsh = search_begin(filename, SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, gamedirname); fh = search_fopen(gsh, 0); /* we do not. let's search for pk3's to sift through */ if (fh < 0) { /* let's search for every pk3 in the gamedir and search for a liblist, one at a time. */ psh = search_begin("*.pk3", SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, gamedirname); /* loop through each pk3 in reverse (newest to old) */ for (int i = search_getsize(psh); i >= 0; i--) { string full = search_getfilename(psh, i); if (!full) continue; sh = search_begin(filename, SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, strcat(gamedirname, "/", full)); fh = search_fopen(sh, 0); //print(sprintf("looking for %s in %s\n", filename, strcat(gamedirname, "/", full))); /* we found one */ if (fh >= 0) { search_end(sh); break; } search_end(sh); } search_end(psh); } /* we do not. let's search for pk3's to sift through */ if (fh < 0) { /* let's search for every pk3 in the gamedir and search for a liblist, one at a time. */ psh = search_begin("dlcache/*.pk3.*", SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, gamedirname); /* loop through each pk3 in reverse (newest to old) */ for (int i = search_getsize(psh); i >= 0; i--) { string full = search_getfilename(psh, i); //print(sprintf("%s\n", full)); if (!full) continue; sh = search_begin(filename, SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, strcat(gamedirname, "/", full)); fh = search_fopen(sh, 0); //print(sprintf("looking for %s in %s\n", filename, strcat(gamedirname, "/", full))); /* we found one */ if (fh >= 0) { search_end(sh); break; } search_end(sh); } search_end(psh); } /* still nothing. let's search for pk4's to sift through */ if (fh < 0) { /* let's search for every pk4 in the gamedir and search for a liblist, one at a time. */ psh = search_begin("*.pk4", SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, gamedirname); /* loop through each pk4 in reverse (newest to old) */ for (int i = search_getsize(psh); i >= 0; i--) { string full = search_getfilename(psh, i); if (!full) continue; sh = search_begin(filename, SB_FULLPACKAGEPATH | SB_FORCESEARCH, FALSE, strcat(gamedirname, "/", full)); fh = search_fopen(sh, 0); /* we found one */ if (fh >= 0) { search_end(sh); break; } search_end(sh); } search_end(psh); } search_end(gsh); return (fh); } /* check if a gameinfo.txt for the gamedir contains gameinfo, parse it if present */ int games_check_gtxt(int id, string gamedirname) { string temp; filestream fh; int ret = 0; fh = games_find_in_gamedir("gameinfo.txt", gamedirname); if (fh < 0) fh = games_find_in_gamedir("GameInfo.txt", gamedirname); /* we have found a liblist.gam */ if (fh >= 0) { string gamedirchain = ""; int braced = 0; while ((temp = fgets(fh))) { string token; tokenize_console(temp); token = strtolower(argv(0)); if (!token) continue; if (token == "{") braced++; if (token == "}") braced--; if (braced == 1) { /* GameInfo */ switch (token) { case "game": games[id].game = argv(1); break; case "type": games[id].type = argv(1); break; } } else if (braced == 2) { /* FileSystem */ switch (token) { case "steamappid": break; case "toolsappid": break; } } else if (braced == 3) { /* SearchPaths */ switch (token) { case "game": if (argv(1) == "|gameinfo_path|.") gamedirchain = strcat(gamedirchain, games[id].gamedir, " "); else gamedirchain = strcat(gamedirchain, argv(1), " "); break; } } } /* in gameinfo.txt files, we list game load-order in reverse */ if (gamedirchain) { string maindir = games[id].gamedir; float c = tokenize(gamedirchain); for (float i = c-1; i >= 0; i--) { if (argv(i) == maindir) continue; if (i == 0) games[id].gamedir = strcat(games[id].gamedir, argv(i)); else games[id].gamedir = strcat(games[id].gamedir, argv(i), ";"); } } fclose(fh); ret = 1; } return (ret); } /* check if a manifest for the gamedir contains gameinfo, parse it if present */ int games_check_manifest(int id, string gamedirname) { int ret = 0; float count; string gamedescription = getgamedirinfo(id, 2); /* no manifest, or no cvar strings inside */ if (gamedescription == "") { return (0); } count = tokenize_console(gamedescription); for (int i = 0; i < count; i++) { string full = argv(i); string first = substring(full, 0, 9); string second = substring(full, 9, -1); /* we may have a game manifest, but if it doesn't * contains any gameinfo entries a different file * should probably be parsed later */ if (first == "gameinfo_") { customgame_liblist_parse(id, second, argv(i+1)); ret = 1; } } return (ret); } /* check if a liblist, parse it if present */ int games_check_liblist(int id, string gamedirname) { string temp; filestream fh; int ret = 0; /* first let's see if we've got a liblist.gam just floating inside the gamedir */ fh = games_find_in_gamedir("liblist.gam", gamedirname); /* we have found a liblist.gam */ if (fh >= 0) { while ((temp = fgets(fh))) { tokenize(temp); customgame_liblist_parse(id, argv(0), argv(1)); } fclose(fh); ret = 1; } return (ret); } void customgame_btnactivate_start(void) { int nextgame = customgame_lbMods.GetSelected(); games_set(nextgame); if (games[nextgame].info_type == GAMEINFO_MANIFEST) localcmd(sprintf("gamedir %s %s.fmf\nfs_changegame %s -\n", games[nextgame].gamedir, games[nextgame].gamedir, games[nextgame].gamedir)); else if (games[nextgame].info_type == GAMEINFO_LIBLIST) { /* some games/mods inherit other directories */ if (games[nextgame].fallback_dir) { localcmd(sprintf("gamedir \"%s;%s;%s\"\n", games[nextgame].base_dir, games[nextgame].fallback_dir, games[nextgame].gamedir)); } else { localcmd(sprintf("gamedir \"%s;%s\"\n", games[nextgame].base_dir, games[nextgame].gamedir)); } } else localcmd(sprintf("gamedir \"%s;%s\"\n", games[nextgame].base_dir, games[nextgame].gamedir)); localcmd("stopmusic\nsnd_restart\nwait\nvid_reload\n"); localcmd("menu_restart\n"); localcmd("menu_customgame\n"); localcmd("menu_musicstart\n"); } void customgame_installstart(int gameid) { int count; count = tokenize(games[gameid].pkgname); for (int i = 0; i < count; i++) { int pkgid = game_getpackageid(argv(i)); localcmd(sprintf("pkg add %s\n", argv(i))); print(sprintf("Marking package %s for install.\n", argv(i))); } game_writeinstallcache(gameid, games[gameid].gamedir); localcmd("pkg apply\n"); print("Starting installation of custom game packages\n"); } void customgame_installend(void) { int gid = g_iModInstallCache; print(sprintf("Installation ended for %S!\n", g_strModInstallCache)); localcmd(sprintf("game %s\n", g_strModInstallCache)); localcmd("stopmusic\nsnd_restart\nwait\nvid_reload\n"); localcmd("menu_restart\n"); localcmd("menu_customgame\n"); localcmd("menu_musicstart\n"); game_writeinstallcache(-1, g_strModInstallCache); } void customgame_installframe(void) { int id; float perc; float c; int loading; /* graphical frame */ customgame_dlgWait.Draw(); WField_Static(162, 180, "Installing mod data...", 320, 260, col_prompt_text, 1.0f, 2, font_label_p); /* download percentage */ perc = 0.0f; loading = FALSE; /* a game can have multiple packages associated */ id = g_iModInstallCache; c = tokenize(games[id].pkgname); /* go through all invididual packages */ for (float i = 0; i < c; i++) { string st; int pkgid; /* package query */ pkgid = game_getpackageid(argv(i)); st = getpackagemanagerinfo(pkgid, GPMI_INSTALLED); /* filter out statuses so we can calculate percentage */ switch (st) { case "": case "pending": case "enabled": case "present": case "corrupt": break; default: perc += stof(st); } /* all packages need to be 'enabled', else fail to end */ if (st != "enabled") loading = TRUE; } /* display download percentage we calculated */ perc = perc / c; WField_Static(162, 220, sprintf("%d%%", perc), 320, 260, [1,1,1], 1.0f, 2, font_label_p); WField_Static(162, 260, "Service provided by frag-net.com through archive.org", 320, 260, [1,1,1], 1.0f, 2, font_label); /* not everything has been downloaded */ if (loading == TRUE) return; customgame_installend(); } /* download the .fmf and switch games immediately */ void customgame_btninstall_start(void) { int id = customgame_lbMods.GetSelected(); string st; st = getpackagemanagerinfo(games[id].pkgid, GPMI_INSTALLED); print(st); print("\n"); if (st != "enabled") { customgame_installstart(id); return; } game_writeinstallcache(id, games[id].gamedir); customgame_installend(); } void customgame_btndeactivate_start(void) { localcmd(sprintf("gamedir %s\n", GAME_DIR)); localcmd("stopmusic\nsnd_restart\nwait\nvid_reload\n"); localcmd("menu_restart\n"); localcmd("menu_customgame\n"); localcmd("menu_musicstart\n"); } 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 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); } } /* set some sane default packages, so that we don't need to ship a custom liblist */ void games_setdefaultpkgs(int id) { if (games[id].gamedir == "valve") { games[id].pkgname = "valve_patch;addon_furtherdata;addon_holidaymodels"; games[id].pkgfile = "maps/crossfire.bsp"; /* only found in patches */ } } void games_init_mods(void) { int id; int foundself = 0; string gamedirname; gameinfo_count = 0; for (id = 0; (gamedirname = getgamedirinfo(id, 0)); id++) { gameinfo_count++; } /* re-allocate the game list */ memfree(games); games = memalloc(sizeof(gameinfo_t) * gameinfo_count); /* The things we do for frequent flyer mileage. */ if (!games) error(sprintf("Attempting to allocate mod data for %i entries failed\n", gameinfo_count)); /* now loop through all the mods we found and load in the metadata */ for (id = 0; id < gameinfo_count; id++) { gamedirname = getgamedirinfo(id, 0); /* Fill in the defaults */ games[id].game = gamedirname; games[id].gamedir = gamedirname; games[id].base_dir = GAME_DIR; games[id].url_info = ""; games[id].url_dl = ""; games[id].version = "1.0"; games[id].size = 0; games[id].type = "Both"; games[id].nomodels = 0; games[id].nosprays = 0; games[id].mpentity = "info_player_deathmatch"; games[id].gamedll = "progs.dat"; games[id].startmap = "map c0a0\n"; games[id].trainingmap = "map t0a0\n"; games[id].cldll = 1; games[id].hlversion = "1000"; games[id].svonly = 0; games[id].installed = 1; games[id].chatroom = gamedirname; games[id].readme = "readme.txt"; games[id].pkgid = -1; games[id].steambg = 0; games_setdefaultpkgs(id); if (games_check_manifest(id, gamedirname) == 1) { NSLog("[MENU] Found manifest for %s", gamedirname); games[id].info_type = GAMEINFO_MANIFEST; } else if (games_check_gtxt(id, gamedirname) == 1) { NSLog("[MENU] Found gameinfo for %s", gamedirname); games[id].info_type = GAMEINFO_GITXT; } else if (games_check_liblist(id, gamedirname) == 1) { NSLog("[MENU] Found liblist for %s", gamedirname); games[id].info_type = GAMEINFO_LIBLIST; } else { NSLog("[MENU] Found nothing for %s", gamedirname); games[id].info_type = GAMEINFO_NONE; } /* if we're this mod, make sure to let the rest of the menu know */ if (games[id].gamedir == cvar_string("game")) { games_set(id); } } /* we may have some mods, but we're not running any of them. Fatal */ if (gameinfo_current == -1) { print("^1FATAL ERROR: NO LIBLIST.GAM FOR CURRENT MOD FOUND!\n"); crash(); return; } } #endif void games_init(void) { int id = 0; string gamedirname = cvar_string("game"); gameinfo_count = 1; /* we start at 1 game, ours */ games = memalloc(sizeof(gameinfo_t) * gameinfo_count); /* Fill in the defaults */ games[id].game = gamedirname; games[id].gamedir = gamedirname; games[id].base_dir = GAME_DIR; games[id].url_info = ""; games[id].url_dl = ""; games[id].version = "1.0"; games[id].size = 0; games[id].type = "Both"; games[id].nomodels = 0; games[id].nosprays = 0; games[id].mpentity = "info_player_deathmatch"; games[id].gamedll = "progs.dat"; games[id].startmap = "map c0a0\n"; games[id].trainingmap = "map t0a0\n"; games[id].cldll = 1; games[id].hlversion = "1000"; games[id].svonly = 0; games[id].installed = 1; games[id].chatroom = cvar_string("gameinfo_chatroom"); if not (games[id].chatroom) { games[id].chatroom = gamedirname; } games[id].readme = "readme.txt"; games[id].pkgid = -1; games[id].steambg = 0; gameinfo_current = 0; /* only run this when not in web-client mode */ #ifndef WEBMENU /* set the default packages for a given game */ games_setdefaultpkgs(id); if (games_check_manifest(id, gamedirname) == 1) { NSLog("[MENU] Found manifest for %s", gamedirname); games[id].info_type = GAMEINFO_MANIFEST; } else if (games_check_gtxt(id, gamedirname) == 1) { NSLog("[MENU] Found gameinfo for %s", gamedirname); games[id].info_type = GAMEINFO_GITXT; } else if (games_check_liblist(id, gamedirname) == 1) { NSLog("[MENU] Found liblist for %s", gamedirname); games[id].info_type = GAMEINFO_LIBLIST; } else { NSLog("[MENU] Found nothing for %s", gamedirname); games[id].info_type = GAMEINFO_NONE; } #endif /* set the current game to be us */ games_set(id); } void menu_customgame_init(void) { #ifndef WEBMENU fn_customgame = spawn(CWidget); customgame_dlgWait = spawn(CDialog); 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); customgame_btnRefresh.SetExecute(ModServer_Refresh); 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,296); Widget_Add(fn_customgame, customgame_frMods); 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); customgame_sbMods.SetPos(141+463,156); customgame_sbMods.SetItemheight(29); customgame_sbMods.SetHeight(289); customgame_sbMods.SetCallback(customgame_sbmods_changed); customgame_sbMods.SetMax(gameinfo_count); Widget_Add(fn_customgame, customgame_sbMods); g_iModInstallCache = -1; #endif } #ifndef WEBMENU var int g_customgame_initialized = 0; #endif void menu_customgame_draw(void) { #ifndef WEBMENU Header_Draw(HEAD_CUSTOM); /* init all the other mod directories here */ if (g_customgame_initialized < 2) { customgame_dlgWait.Draw(); WField_Static(162, 180, "Indexing all local games, please wait...", 320, 260, col_prompt_text, 1.0f, 2, font_label_p); /* once we started rendering the message, start parsing mods */ if (g_customgame_initialized == 1) games_init_mods(); g_customgame_initialized++; return; } Widget_Draw(fn_customgame); WLabel_Static(155, 143, m_reslbl[IDS_MODLIST_TYPE], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(201, 143, m_reslbl[IDS_MODLIST_NAME], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(321, 143, m_reslbl[IDS_MODLIST_VERSION], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(371, 143, m_reslbl[IDS_MODLIST_SIZE], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(421, 143, m_reslbl[IDS_MODLIST_RATING], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(471, 143, m_reslbl[IDS_MODLIST_INSTALLED], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(521, 143, m_reslbl[IDS_MODLIST_SERVERS], 11, 11, [1,1,1], 1.0f, 0, font_arial); WLabel_Static(571, 143, m_reslbl[IDS_MODLIST_PLAYERS], 11, 11, [1,1,1], 1.0f, 0, font_arial); /* draw a frame for when we're refreshing the mod list */ 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); } /* draw a frame with progress during package install */ if (g_iModInstallCache >= 0i) { customgame_installframe(); } customgame_sbMods.SetMax(gameinfo_count-1); #endif } void menu_customgame_input(float evtype, float scanx, float chary, float devid) { #ifndef WEBMENU Widget_Input(fn_customgame, evtype, scanx, chary, devid); #endif }