Session_menu.cpp 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Session_local.h"
  23. //#include <time.h> //bc
  24. idCVar idSessionLocal::gui_configServerRate( "gui_configServerRate", "0", CVAR_GUI | CVAR_ARCHIVE | CVAR_ROM | CVAR_INTEGER, "" );
  25. // implements the setup for, and commands from, the main menu
  26. /*
  27. ==============
  28. idSessionLocal::GetActiveMenu
  29. ==============
  30. */
  31. idUserInterface *idSessionLocal::GetActiveMenu( void ) {
  32. return guiActive;
  33. }
  34. /*
  35. ==============
  36. idSessionLocal::StartMainMenu
  37. ==============
  38. */
  39. void idSessionLocal::StartMenu( bool playIntro ) {
  40. if ( guiActive == guiMainMenu ) {
  41. return;
  42. }
  43. if ( readDemo ) {
  44. // if we're playing a demo, esc kills it
  45. UnloadMap();
  46. }
  47. // pause the game sound world
  48. if ( sw != NULL && !sw->IsPaused() ) {
  49. sw->Pause();
  50. }
  51. // start playing the menu sounds
  52. soundSystem->SetPlayingSoundWorld( menuSoundWorld );
  53. SetGUI( guiMainMenu, NULL );
  54. guiMainMenu->HandleNamedEvent( playIntro ? "playIntro" : "noIntro" );
  55. if(fileSystem->HasD3XP()) {
  56. guiMainMenu->SetStateString("game_list", common->GetLanguageDict()->GetString( "#str_07202" ));
  57. } else {
  58. guiMainMenu->SetStateString("game_list", common->GetLanguageDict()->GetString( "#str_07212" ));
  59. }
  60. console->Close();
  61. }
  62. /*
  63. =================
  64. idSessionLocal::SetGUI
  65. =================
  66. */
  67. void idSessionLocal::SetGUI( idUserInterface *gui, HandleGuiCommand_t handle ) {
  68. const char *cmd;
  69. guiActive = gui;
  70. guiHandle = handle;
  71. if ( guiMsgRestore ) {
  72. common->DPrintf( "idSessionLocal::SetGUI: cleared an active message box\n" );
  73. guiMsgRestore = NULL;
  74. }
  75. if ( !guiActive ) {
  76. return;
  77. }
  78. if ( guiActive == guiMainMenu ) {
  79. SetSaveGameGuiVars();
  80. SetMainMenuGuiVars();
  81. } else if ( guiActive == guiRestartMenu )
  82. {
  83. //BC RESTART
  84. SetSaveGameGuiVars();
  85. }
  86. sysEvent_t ev;
  87. memset( &ev, 0, sizeof( ev ) );
  88. ev.evType = SE_NONE;
  89. cmd = guiActive->HandleEvent( &ev, com_frameTime );
  90. guiActive->Activate( true, com_frameTime );
  91. }
  92. /*
  93. ===============
  94. idSessionLocal::ExitMenu
  95. ===============
  96. */
  97. void idSessionLocal::ExitMenu( void ) {
  98. guiActive = NULL;
  99. // go back to the game sounds
  100. soundSystem->SetPlayingSoundWorld( sw );
  101. // unpause the game sound world
  102. if ( sw != NULL && sw->IsPaused() ) {
  103. sw->UnPause();
  104. }
  105. }
  106. /*
  107. ===============
  108. idListSaveGameCompare
  109. ===============
  110. */
  111. ID_INLINE int idListSaveGameCompare( const fileTIME_T *a, const fileTIME_T *b ) {
  112. return b->timeStamp - a->timeStamp;
  113. }
  114. /*
  115. ===============
  116. idSessionLocal::GetSaveGameList
  117. ===============
  118. */
  119. void idSessionLocal::GetSaveGameList( idStrList &fileList, idList<fileTIME_T> &fileTimes ) {
  120. int i;
  121. idFileList *files;
  122. // NOTE: no fs_game_base for savegames
  123. idStr game = cvarSystem->GetCVarString( "fs_game" );
  124. if( game.Length() ) {
  125. files = fileSystem->ListFiles( "savegames", ".save", false, false, game );
  126. } else {
  127. files = fileSystem->ListFiles( "savegames", ".save" );
  128. }
  129. fileList = files->GetList();
  130. fileSystem->FreeFileList( files );
  131. for ( i = 0; i < fileList.Num(); i++ ) {
  132. ID_TIME_T timeStamp;
  133. fileSystem->ReadFile( "savegames/" + fileList[i], NULL, &timeStamp );
  134. fileList[i].StripLeading( '/' );
  135. fileList[i].StripFileExtension();
  136. fileTIME_T ft;
  137. ft.index = i;
  138. ft.timeStamp = timeStamp;
  139. fileTimes.Append( ft );
  140. }
  141. fileTimes.Sort( idListSaveGameCompare );
  142. }
  143. /*
  144. ===============
  145. idSessionLocal::SetSaveGameGuiVars
  146. ===============
  147. */
  148. void idSessionLocal::SetSaveGameGuiVars( void ) {
  149. int i;
  150. idStr name;
  151. idStrList fileList;
  152. idList<fileTIME_T> fileTimes;
  153. loadGameList.Clear();
  154. fileList.Clear();
  155. fileTimes.Clear();
  156. GetSaveGameList( fileList, fileTimes );
  157. loadGameList.SetNum( fileList.Num() );
  158. for ( i = 0; i < fileList.Num(); i++ ) {
  159. loadGameList[i] = fileList[fileTimes[i].index];
  160. idLexer src(LEXFL_NOERRORS|LEXFL_NOSTRINGCONCAT);
  161. if ( src.LoadFile( va("savegames/%s.txt", loadGameList[i].c_str()) ) ) {
  162. idToken tok;
  163. src.ReadToken( &tok );
  164. name = tok;
  165. } else {
  166. name = loadGameList[i];
  167. }
  168. name += "\t";
  169. idStr date = Sys_TimeStampToStr( fileTimes[i].timeStamp );
  170. //bc 9-1-2015 show date as "today" "yesterday" "2 days ago" etc.
  171. //first extract the time string.
  172. idStr timeofday;
  173. int timetab;
  174. time_t today;
  175. time_t filetimestamp;
  176. time_t timediff;
  177. struct tm *timeinfo;
  178. int days;
  179. idStr diffString;
  180. timetab = date.Find( '\t' );
  181. timeofday = date.Right( date.Length() - timetab - 1);
  182. timeofday.StripTrailingWhitespace(); //remove whitespace.
  183. timeofday.StripLeading( ' ' ); //remove whitespace.
  184. timeofday.ToUpper(); //force lower case.
  185. //now parse the date string.
  186. filetimestamp = fileTimes[i].timeStamp;
  187. time(&today);
  188. timediff = (today - filetimestamp);
  189. timeinfo = gmtime(&timediff);
  190. days = timeinfo->tm_yday;
  191. switch (days)
  192. {
  193. case 0:
  194. diffString = "TODAY";
  195. break;
  196. case 1:
  197. diffString = "YESTERDAY";
  198. break;
  199. default:
  200. diffString = va("%d DAYS AGO", days);
  201. break;
  202. }
  203. name += va("%s\t%s", diffString.c_str(), timeofday.c_str());
  204. //END OF SHOWDATE CODE.
  205. guiActive->SetStateString( va("loadgame_item_%i", i), name);
  206. }
  207. guiActive->DeleteStateVar( va("loadgame_item_%i", fileList.Num()) );
  208. guiActive->SetStateString( "loadgame_sel_0", "-1" );
  209. guiActive->SetStateString( "loadgame_shot", "guis/assets/blankLevelShot" );
  210. }
  211. /*
  212. ===============
  213. idSessionLocal::SetModsMenuGuiVars
  214. ===============
  215. */
  216. void idSessionLocal::SetModsMenuGuiVars( void ) {
  217. int i;
  218. idModList *list = fileSystem->ListMods();
  219. int totalNumberOfMods = list->GetNumMods();
  220. modsList.SetNum( totalNumberOfMods );
  221. // Build the local mods gui list
  222. for ( i = 0; i < list->GetNumMods(); i++ )
  223. {
  224. idStr modName;
  225. modName = list->GetDescription( i );
  226. modName += "\t";
  227. modName += "Local";
  228. guiActive->SetStateString( va("modsList_item_%i", i), modName.c_str() );
  229. common->Printf("MOD: local mod path: %s\n", list->GetMod( i ));
  230. modsList[i] = list->GetMod( i );
  231. }
  232. guiActive->DeleteStateVar( va("modsList_item_%i", totalNumberOfMods) );
  233. guiActive->SetStateString( "modsList_sel_0", "-1" );
  234. fileSystem->FreeModList( list );
  235. }
  236. /*
  237. ===============
  238. idSessionLocal::SetMainMenuSkin
  239. ===============
  240. */
  241. void idSessionLocal::SetMainMenuSkin( void ) {
  242. // skins
  243. idStr str = cvarSystem->GetCVarString( "mod_validSkins" );
  244. idStr uiSkin = cvarSystem->GetCVarString( "ui_skin" );
  245. idStr skin;
  246. int skinId = 1;
  247. int count = 1;
  248. while ( str.Length() ) {
  249. int n = str.Find( ";" );
  250. if ( n >= 0 ) {
  251. skin = str.Left( n );
  252. str = str.Right( str.Length() - n - 1 );
  253. } else {
  254. skin = str;
  255. str = "";
  256. }
  257. if ( skin.Icmp( uiSkin ) == 0 ) {
  258. skinId = count;
  259. }
  260. count++;
  261. }
  262. for ( int i = 0; i < count; i++ ) {
  263. guiMainMenu->SetStateInt( va( "skin%i", i+1 ), 0 );
  264. }
  265. guiMainMenu->SetStateInt( va( "skin%i", skinId ), 1 );
  266. }
  267. /*
  268. ===============
  269. idSessionLocal::SetPbMenuGuiVars
  270. ===============
  271. */
  272. void idSessionLocal::SetPbMenuGuiVars( void ) {
  273. }
  274. /*
  275. ===============
  276. idSessionLocal::SetMainMenuGuiVars
  277. ===============
  278. */
  279. void idSessionLocal::SetMainMenuGuiVars( void ) {
  280. guiMainMenu->SetStateString( "serverlist_sel_0", "-1" );
  281. guiMainMenu->SetStateString( "serverlist_selid_0", "-1" );
  282. guiMainMenu->SetStateInt( "com_machineSpec", com_machineSpec.GetInteger() );
  283. // "inetGame" will hold a hand-typed inet address, which is not archived to a cvar
  284. guiMainMenu->SetStateString( "inetGame", "" );
  285. // key bind names
  286. guiMainMenu->SetKeyBindingNames();
  287. // flag for in-game menu
  288. if ( mapSpawned ) {
  289. guiMainMenu->SetStateString( "inGame", IsMultiplayer() ? "2" : "1" );
  290. } else {
  291. guiMainMenu->SetStateString( "inGame", "0" );
  292. }
  293. SetCDKeyGuiVars( );
  294. #ifdef ID_DEMO_BUILD
  295. guiMainMenu->SetStateString( "nightmare", "0" );
  296. #else
  297. guiMainMenu->SetStateString( "nightmare", cvarSystem->GetCVarBool( "g_nightmare" ) ? "1" : "0" );
  298. #endif
  299. guiMainMenu->SetStateString( "browser_levelshot", "guis/assets/splash/pdtempa" );
  300. SetMainMenuSkin();
  301. // Mods Menu
  302. SetModsMenuGuiVars();
  303. //bc
  304. //guiMsg->SetStateString( "visible_hasxp", fileSystem->HasD3XP() ? "1" : "0" );
  305. #if defined( __linux__ )
  306. guiMainMenu->SetStateString( "driver_prompt", "1" );
  307. #else
  308. guiMainMenu->SetStateString( "driver_prompt", "0" );
  309. #endif
  310. //BC demo build.
  311. guiMainMenu->SetStateBool( "isdemo", cvarSystem->GetCVarBool("g_demo"));
  312. SetPbMenuGuiVars();
  313. }
  314. /*
  315. ==============
  316. idSessionLocal::HandleSaveGameMenuCommands
  317. ==============
  318. */
  319. bool idSessionLocal::HandleSaveGameMenuCommand( idCmdArgs &args, int &icmd ) {
  320. const char *cmd = args.Argv(icmd-1);
  321. if ( !idStr::Icmp( cmd, "loadGame" ) ) {
  322. int choice = guiActive->State().GetInt("loadgame_sel_0");
  323. if ( choice >= 0 && choice < loadGameList.Num() ) {
  324. sessLocal.LoadGame( loadGameList[choice] );
  325. }
  326. return true;
  327. }
  328. if ( !idStr::Icmp( cmd, "saveGame" ) ) {
  329. const char *saveGameName = guiActive->State().GetString("saveGameName");
  330. if ( saveGameName && saveGameName[0] ) {
  331. // First see if the file already exists unless they pass '1' to authorize the overwrite
  332. if ( icmd == args.Argc() || atoi(args.Argv( icmd++ )) == 0 ) {
  333. idStr saveFileName = saveGameName;
  334. sessLocal.ScrubSaveGameFileName( saveFileName );
  335. saveFileName = "savegames/" + saveFileName;
  336. saveFileName.SetFileExtension(".save");
  337. idStr game = cvarSystem->GetCVarString( "fs_game" );
  338. idFile *file;
  339. if(game.Length()) {
  340. file = fileSystem->OpenFileRead( saveFileName, true, game );
  341. } else {
  342. file = fileSystem->OpenFileRead( saveFileName );
  343. }
  344. if ( file != NULL ) {
  345. fileSystem->CloseFile( file );
  346. // The file exists, see if it's an autosave
  347. saveFileName.SetFileExtension(".txt");
  348. idLexer src(LEXFL_NOERRORS|LEXFL_NOSTRINGCONCAT);
  349. if ( src.LoadFile( saveFileName ) ) {
  350. idToken tok;
  351. src.ReadToken( &tok ); // Name
  352. src.ReadToken( &tok ); // Map
  353. src.ReadToken( &tok ); // Screenshot
  354. if ( !tok.IsEmpty() ) {
  355. // NOTE: base/ gui doesn't handle that one
  356. guiActive->HandleNamedEvent( "autosaveOverwriteError" );
  357. return true;
  358. }
  359. }
  360. guiActive->HandleNamedEvent( "saveGameOverwrite" );
  361. return true;
  362. }
  363. }
  364. sessLocal.SaveGame( saveGameName );
  365. SetSaveGameGuiVars( );
  366. guiActive->StateChanged( com_frameTime );
  367. }
  368. return true;
  369. }
  370. if ( !idStr::Icmp( cmd, "deleteGame" ) )
  371. {
  372. int choice = guiActive->State().GetInt( "loadgame_sel_0" );
  373. if ( choice >= 0 && choice < loadGameList.Num() )
  374. {
  375. fileSystem->RemoveFile( va("savegames/%s.save", loadGameList[choice].c_str()) );
  376. fileSystem->RemoveFile( va("savegames/%s.tga", loadGameList[choice].c_str()) );
  377. fileSystem->RemoveFile( va("savegames/%s.txt", loadGameList[choice].c_str()) );
  378. SetSaveGameGuiVars( );
  379. //BC 4-22-2016 select last item in list after deleting.
  380. if (loadGameList.Num() > 0)
  381. {
  382. guiActive->SetStateString( "loadgame_sel_0", va("%d", loadGameList.Num() - 1) );
  383. }
  384. guiActive->StateChanged( com_frameTime );
  385. }
  386. return true;
  387. }
  388. if ( !idStr::Icmp( cmd, "updateSaveGameInfo" ) ) {
  389. int choice = guiActive->State().GetInt( "loadgame_sel_0" );
  390. if ( choice >= 0 && choice < loadGameList.Num() ) {
  391. const idMaterial *material;
  392. idStr saveName, description, screenshot;
  393. idLexer src(LEXFL_NOERRORS|LEXFL_NOSTRINGCONCAT);
  394. if ( src.LoadFile( va("savegames/%s.txt", loadGameList[choice].c_str()) ) ) {
  395. idToken tok;
  396. src.ReadToken( &tok );
  397. saveName = tok;
  398. src.ReadToken( &tok );
  399. description = tok;
  400. src.ReadToken( &tok );
  401. screenshot = tok;
  402. } else {
  403. saveName = loadGameList[choice];
  404. description = loadGameList[choice];
  405. screenshot = "";
  406. }
  407. if ( screenshot.Length() == 0 ) {
  408. screenshot = va("savegames/%s.tga", loadGameList[choice].c_str());
  409. }
  410. material = declManager->FindMaterial( screenshot );
  411. if ( material ) {
  412. material->ReloadImages( false );
  413. }
  414. guiActive->SetStateString( "loadgame_shot", screenshot );
  415. saveName.RemoveColors();
  416. guiActive->SetStateString( "saveGameName", saveName );
  417. guiActive->SetStateString( "saveGameDescription", description );
  418. ID_TIME_T timeStamp;
  419. fileSystem->ReadFile( va("savegames/%s.save", loadGameList[choice].c_str()), NULL, &timeStamp );
  420. idStr date = Sys_TimeStampToStr(timeStamp);
  421. int tab = date.Find( '\t' );
  422. idStr time = date.Right( date.Length() - tab - 1);
  423. guiActive->SetStateString( "saveGameDate", date.Left( tab ) );
  424. guiActive->SetStateString( "saveGameTime", time + "z" );
  425. }
  426. return true;
  427. }
  428. return false;
  429. }
  430. /*
  431. ==============
  432. idSessionLocal::HandleRestartMenuCommands
  433. Executes any commands returned by the gui
  434. ==============
  435. */
  436. void idSessionLocal::HandleRestartMenuCommands( const char *menuCommand ) {
  437. // execute the command from the menu
  438. int icmd;
  439. idCmdArgs args;
  440. args.TokenizeString( menuCommand, false );
  441. for( icmd = 0; icmd < args.Argc(); ) {
  442. const char *cmd = args.Argv( icmd++ );
  443. if ( HandleSaveGameMenuCommand( args, icmd ) ) {
  444. continue;
  445. }
  446. if ( !idStr::Icmp( cmd, "restart" ) ) {
  447. if ( !LoadGame( GetAutoSaveName( mapSpawnData.serverInfo.GetString("si_map") ) ) ) {
  448. // If we can't load the autosave then just restart the map
  449. MoveToNewMap( mapSpawnData.serverInfo.GetString("si_map") );
  450. }
  451. continue;
  452. }
  453. if ( !idStr::Icmp( cmd, "quit" ) ) {
  454. ExitMenu();
  455. common->Quit();
  456. return;
  457. }
  458. if ( !idStr::Icmp ( cmd, "exec" ) ) {
  459. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, args.Argv( icmd++ ) );
  460. continue;
  461. }
  462. if ( !idStr::Icmp( cmd, "play" ) ) {
  463. if ( args.Argc() - icmd >= 1 ) {
  464. idStr snd = args.Argv(icmd++);
  465. sw->PlayShaderDirectly(snd);
  466. }
  467. continue;
  468. }
  469. }
  470. }
  471. /*
  472. ==============
  473. idSessionLocal::HandleIntroMenuCommands
  474. Executes any commands returned by the gui
  475. ==============
  476. */
  477. void idSessionLocal::HandleIntroMenuCommands( const char *menuCommand ) {
  478. // execute the command from the menu
  479. int i;
  480. idCmdArgs args;
  481. args.TokenizeString( menuCommand, false );
  482. for( i = 0; i < args.Argc(); ) {
  483. const char *cmd = args.Argv( i++ );
  484. if ( !idStr::Icmp( cmd, "startGame" ) ) {
  485. menuSoundWorld->ClearAllSoundEmitters();
  486. ExitMenu();
  487. continue;
  488. }
  489. if ( !idStr::Icmp( cmd, "play" ) ) {
  490. if ( args.Argc() - i >= 1 ) {
  491. idStr snd = args.Argv(i++);
  492. menuSoundWorld->PlayShaderDirectly(snd);
  493. }
  494. continue;
  495. }
  496. }
  497. }
  498. /*
  499. ==============
  500. idSessionLocal::UpdateMPLevelShot
  501. ==============
  502. */
  503. void idSessionLocal::UpdateMPLevelShot( void ) {
  504. char screenshot[ MAX_STRING_CHARS ];
  505. fileSystem->FindMapScreenshot( cvarSystem->GetCVarString( "si_map" ), screenshot, MAX_STRING_CHARS );
  506. guiMainMenu->SetStateString( "current_levelshot", screenshot );
  507. }
  508. /*
  509. ==============
  510. idSessionLocal::HandleMainMenuCommands
  511. Executes any commands returned by the gui
  512. ==============
  513. */
  514. void idSessionLocal::HandleMainMenuCommands( const char *menuCommand ) {
  515. // execute the command from the menu
  516. int icmd;
  517. idCmdArgs args;
  518. args.TokenizeString( menuCommand, false );
  519. for( icmd = 0; icmd < args.Argc(); ) {
  520. const char *cmd = args.Argv( icmd++ );
  521. if ( HandleSaveGameMenuCommand( args, icmd ) ) {
  522. continue;
  523. }
  524. // always let the game know the command is being run
  525. if ( game ) {
  526. game->HandleMainMenuCommands( cmd, guiActive );
  527. }
  528. if ( !idStr::Icmp( cmd, "startGame" ) ) {
  529. //bc
  530. cvarSystem->SetCVarInteger( "g_commentary", guiMainMenu->State().GetInt( "commentary" ) );
  531. cvarSystem->SetCVarInteger( "g_skill", guiMainMenu->State().GetInt( "skill" ) );
  532. if ( icmd < args.Argc() ) {
  533. StartNewGame( args.Argv( icmd++ ) );
  534. } else {
  535. #ifndef ID_DEMO_BUILD
  536. StartNewGame( "game/mars_city1" );
  537. #else
  538. StartNewGame( "game/demo_mars_city1" );
  539. #endif
  540. }
  541. // need to do this here to make sure com_frameTime is correct or the gui activates with a time that
  542. // is "however long map load took" time in the past
  543. common->GUIFrame( false, false );
  544. SetGUI( guiIntro, NULL );
  545. guiIntro->StateChanged( com_frameTime, true );
  546. // stop playing the game sounds
  547. soundSystem->SetPlayingSoundWorld( menuSoundWorld );
  548. continue;
  549. }
  550. if ( !idStr::Icmp( cmd, "quit" ) ) {
  551. ExitMenu();
  552. common->Quit();
  553. return;
  554. }
  555. if ( !idStr::Icmp( cmd, "loadMod" ) )
  556. {
  557. int choice = guiActive->State().GetInt( "modsList_sel_0" );
  558. if ( choice >= 0 && choice < modsList.Num() )
  559. {
  560. cvarSystem->SetCVarString( "fs_game", modsList[ choice ] );
  561. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "reloadEngine menu\n" );
  562. }
  563. }
  564. if ( !idStr::Icmp( cmd, "UpdateServers" ) ) {
  565. if ( guiActive->State().GetBool( "lanSet" ) ) {
  566. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "LANScan" );
  567. } else {
  568. idAsyncNetwork::GetNETServers();
  569. }
  570. continue;
  571. }
  572. if ( !idStr::Icmp( cmd, "RefreshServers" ) ) {
  573. if ( guiActive->State().GetBool( "lanSet" ) ) {
  574. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "LANScan" );
  575. } else {
  576. idAsyncNetwork::client.serverList.NetScan( );
  577. }
  578. continue;
  579. }
  580. if ( !idStr::Icmp( cmd, "FilterServers" ) ) {
  581. idAsyncNetwork::client.serverList.ApplyFilter( );
  582. continue;
  583. }
  584. if ( !idStr::Icmp( cmd, "sortServerName" ) ) {
  585. idAsyncNetwork::client.serverList.SetSorting( SORT_SERVERNAME );
  586. continue;
  587. }
  588. if ( !idStr::Icmp( cmd, "sortGame" ) ) {
  589. idAsyncNetwork::client.serverList.SetSorting( SORT_GAME );
  590. continue;
  591. }
  592. if ( !idStr::Icmp( cmd, "sortPlayers" ) ) {
  593. idAsyncNetwork::client.serverList.SetSorting( SORT_PLAYERS );
  594. continue;
  595. }
  596. if ( !idStr::Icmp( cmd, "sortPing" ) ) {
  597. idAsyncNetwork::client.serverList.SetSorting( SORT_PING );
  598. continue;
  599. }
  600. if ( !idStr::Icmp( cmd, "sortGameType" ) ) {
  601. idAsyncNetwork::client.serverList.SetSorting( SORT_GAMETYPE );
  602. continue;
  603. }
  604. if ( !idStr::Icmp( cmd, "sortMap" ) ) {
  605. idAsyncNetwork::client.serverList.SetSorting( SORT_MAP );
  606. continue;
  607. }
  608. if ( !idStr::Icmp( cmd, "serverList" ) ) {
  609. idAsyncNetwork::client.serverList.GUIUpdateSelected();
  610. continue;
  611. }
  612. if ( !idStr::Icmp( cmd, "LANConnect" ) ) {
  613. int sel = guiActive->State().GetInt( "serverList_selid_0" );
  614. cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "Connect %d\n", sel ) );
  615. return;
  616. }
  617. if ( !idStr::Icmp( cmd, "MAPScan" ) ) {
  618. const char *gametype = cvarSystem->GetCVarString( "si_gameType" );
  619. if ( gametype == NULL || *gametype == 0 || idStr::Icmp( gametype, "singleplayer" ) == 0 ) {
  620. gametype = "Deathmatch";
  621. }
  622. int i, num;
  623. idStr si_map = cvarSystem->GetCVarString("si_map");
  624. const idDict *dict;
  625. guiMainMenu_MapList->Clear();
  626. guiMainMenu_MapList->SetSelection( 0 );
  627. num = fileSystem->GetNumMaps();
  628. for ( i = 0; i < num; i++ ) {
  629. dict = fileSystem->GetMapDecl( i );
  630. if ( dict && dict->GetBool( gametype ) ) {
  631. const char *mapName = dict->GetString( "name" );
  632. if ( mapName[ 0 ] == '\0' ) {
  633. mapName = dict->GetString( "path" );
  634. }
  635. mapName = common->GetLanguageDict()->GetString( mapName );
  636. guiMainMenu_MapList->Add( i, mapName );
  637. if ( !si_map.Icmp( dict->GetString( "path" ) ) ) {
  638. guiMainMenu_MapList->SetSelection( guiMainMenu_MapList->Num() - 1 );
  639. }
  640. }
  641. }
  642. i = guiMainMenu_MapList->GetSelection( NULL, 0 );
  643. if ( i >= 0 ) {
  644. dict = fileSystem->GetMapDecl( i);
  645. } else {
  646. dict = NULL;
  647. }
  648. cvarSystem->SetCVarString( "si_map", ( dict ? dict->GetString( "path" ) : "" ) );
  649. // set the current level shot
  650. UpdateMPLevelShot();
  651. continue;
  652. }
  653. if ( !idStr::Icmp( cmd, "loadlatestsave" ) )
  654. {
  655. int i;
  656. idStr name;
  657. idStrList fileList;
  658. idList<fileTIME_T> fileTimes;
  659. loadGameList.Clear();
  660. fileList.Clear();
  661. fileTimes.Clear();
  662. GetSaveGameList( fileList, fileTimes );
  663. loadGameList.SetNum( fileList.Num() );
  664. for ( i = 0; i < fileList.Num(); i++ )
  665. {
  666. loadGameList[i] = fileList[fileTimes[i].index];
  667. //attempt to load. if successful, then return. if fail, then try loading the next one.
  668. if (sessLocal.LoadGame( loadGameList[i].c_str() ))
  669. {
  670. return;
  671. }
  672. }
  673. }
  674. //BC
  675. if ( !idStr::Icmp( cmd, "spmapscan" ) )
  676. {
  677. void *buffer;
  678. idStr rawDictionary;
  679. int i;
  680. if (fileSystem->ReadFile( "maplist.txt", &buffer) > 0)
  681. {
  682. rawDictionary = (char *) buffer;
  683. fileSystem->FreeFile( buffer );
  684. }
  685. else
  686. {
  687. common->Printf("ERROR: unable to load maplist.txt\n");
  688. continue;
  689. }
  690. guiMainMenu_spMapList->Clear();
  691. guiMainMenu_spMapList->SetSelection( 0 );
  692. rawDictionary.StripTrailingWhitespace(); //remove whitespace.
  693. rawDictionary.StripLeading( ' ' ); //remove whitespace.
  694. rawDictionary.ToUpper();
  695. idStrList mapnames;
  696. mapnames.Clear();
  697. spMapList.Clear();
  698. while ( 1 )
  699. {
  700. int carriageIdx = Max( rawDictionary.Find('\n',0), rawDictionary.Find('\r',0) );
  701. //common->Printf("%d %d\n", rawDictionary.Find('\n',0), rawDictionary.Find('\r',0));
  702. if (carriageIdx < 0)
  703. {
  704. carriageIdx = rawDictionary.Length();
  705. }
  706. idStr workStr = rawDictionary.Mid(0, carriageIdx);
  707. idStr mapnameshort = workStr;
  708. mapnameshort.StripTrailingWhitespace(); //remove whitespace.
  709. mapnameshort.StripLeading( ' ' ); //remove whitespace.
  710. mapnameshort.ToLower();
  711. idStr mapnamelong = GetAutoSaveName(mapnameshort.c_str());
  712. //mapnames.AddUnique(rawDictionary.Mid(i+1, rawDictionary.Length() ));
  713. mapnames.AddUnique(mapnamelong);
  714. mapnameshort.ToLower();
  715. spMapList.AddUnique(mapnameshort);
  716. rawDictionary = rawDictionary.Mid(carriageIdx + 1, rawDictionary.Length() - carriageIdx - 1); //strip
  717. if (rawDictionary.Length() <= 0)
  718. break;
  719. }
  720. for (i = 0; i < mapnames.Num(); i++)
  721. {
  722. guiMainMenu_spMapList->Add(i, mapnames[i]);
  723. }
  724. if (spMapList.Num() > 0)
  725. guiMainMenu->SetStateString( "current_levelshot", va("guis/assets/thumbs/%s", spMapList[0].c_str()) );
  726. //bc august 2015
  727. //set the gui done marks.
  728. guiMainMenu->SetStateBool("donemark_0", cvarSystem->GetCVarBool("g_leveldone_0"));
  729. guiMainMenu->SetStateBool("donemark_1", cvarSystem->GetCVarBool("g_leveldone_1"));
  730. guiMainMenu->SetStateBool("donemark_2", cvarSystem->GetCVarBool("g_leveldone_2"));
  731. guiMainMenu->SetStateBool("donemark_3", cvarSystem->GetCVarBool("g_leveldone_3"));
  732. guiMainMenu->SetStateBool("donemark_4", cvarSystem->GetCVarBool("g_leveldone_4"));
  733. guiMainMenu->SetStateBool("donemark_5", cvarSystem->GetCVarBool("g_leveldone_5"));
  734. guiMainMenu->SetStateBool("donemark_6", cvarSystem->GetCVarBool("g_leveldone_6"));
  735. guiMainMenu->SetStateBool("donemark_7", cvarSystem->GetCVarBool("g_leveldone_7"));
  736. guiMainMenu->SetStateBool("donemark_8", cvarSystem->GetCVarBool("g_leveldone_8"));
  737. guiMainMenu->SetStateBool("donemark_9", cvarSystem->GetCVarBool("g_leveldone_9"));
  738. guiMainMenu->SetStateBool("donemark_10", cvarSystem->GetCVarBool("g_leveldone_10"));
  739. guiMainMenu->SetStateBool("donemark_11", cvarSystem->GetCVarBool("g_leveldone_11"));
  740. guiMainMenu->SetStateBool("donemark_12", cvarSystem->GetCVarBool("g_leveldone_12"));
  741. guiMainMenu->SetStateBool("donemark_13", cvarSystem->GetCVarBool("g_leveldone_13"));
  742. guiMainMenu->SetStateBool("donemark_14", cvarSystem->GetCVarBool("g_leveldone_14"));
  743. guiMainMenu->SetStateBool("donemark_15", cvarSystem->GetCVarBool("g_leveldone_15"));
  744. guiMainMenu->SetStateBool("donemark_16", cvarSystem->GetCVarBool("g_leveldone_16"));
  745. guiMainMenu->SetStateBool("donemark_17", cvarSystem->GetCVarBool("g_leveldone_17"));
  746. guiMainMenu->SetStateBool("donemark_18", cvarSystem->GetCVarBool("g_leveldone_18"));
  747. guiMainMenu->SetStateBool("donemark_19", cvarSystem->GetCVarBool("g_leveldone_19"));
  748. guiMainMenu->SetStateBool("donemark_20", cvarSystem->GetCVarBool("g_leveldone_20"));
  749. guiMainMenu->SetStateBool("donemark_21", cvarSystem->GetCVarBool("g_leveldone_21"));
  750. guiMainMenu->SetStateBool("donemark_22", cvarSystem->GetCVarBool("g_leveldone_22"));
  751. guiMainMenu->SetStateBool("donemark_23", cvarSystem->GetCVarBool("g_leveldone_23"));
  752. guiMainMenu->SetStateBool("donemark_24", cvarSystem->GetCVarBool("g_leveldone_24"));
  753. guiMainMenu->SetStateBool("donemark_25", cvarSystem->GetCVarBool("g_leveldone_25"));
  754. guiMainMenu->SetStateBool("donemark_26", cvarSystem->GetCVarBool("g_leveldone_26"));
  755. guiMainMenu->SetStateBool("donemark_27", cvarSystem->GetCVarBool("g_leveldone_27"));
  756. guiMainMenu->SetStateBool("donemark_28", cvarSystem->GetCVarBool("g_leveldone_28"));
  757. guiMainMenu->SetStateBool("donemark_29", cvarSystem->GetCVarBool("g_leveldone_29"));
  758. guiMainMenu->SetStateBool("donemark_30", cvarSystem->GetCVarBool("g_leveldone_30"));
  759. guiMainMenu->SetStateBool("donemark_31", cvarSystem->GetCVarBool("g_leveldone_31"));
  760. continue;
  761. }
  762. if ( !idStr::Icmp( cmd, "sp_start" ) )
  763. {
  764. menuSoundWorld->ClearAllSoundEmitters();
  765. ExitMenu();
  766. cvarSystem->SetCVarInteger( "g_commentary", guiMainMenu->State().GetInt( "commentary" ) );
  767. cvarSystem->SetCVarInteger( "g_skill", guiMainMenu->State().GetInt( "skill" ) );
  768. int listIdx = guiMainMenu_spMapList->GetSelection( NULL, 0 );
  769. HandleMainMenuCommands(va("startgame %s", spMapList[listIdx].c_str()));
  770. }
  771. if ( !idStr::Icmp( cmd, "click_mapList" ) )
  772. {
  773. int mapNum = guiMainMenu_spMapList->GetSelection( NULL, 0 );
  774. const idDict *dict = fileSystem->GetMapDecl( mapNum );
  775. if ( dict )
  776. {
  777. cvarSystem->SetCVarString( "si_map", dict->GetString( "path" ) );
  778. }
  779. UpdateMPLevelShot();
  780. continue;
  781. }
  782. if ( !idStr::Icmp( cmd, "click_spmapList" ) )
  783. {
  784. if (spMapList.Num() <= 0)
  785. continue;
  786. int mapNum = guiMainMenu_spMapList->GetSelection( NULL, 0 );
  787. if (mapNum < 0)
  788. continue;
  789. guiMainMenu->SetStateString( "current_levelshot", va("guis/assets/thumbs/%s", spMapList[mapNum].c_str()) );
  790. continue;
  791. }
  792. if ( !idStr::Icmp( cmd, "sendbugreport" ) )
  793. {
  794. idStr rawText = guiMainMenu->State().GetString("reportabug_text");
  795. rawText.StripTrailingWhitespace();
  796. rawText.StripLeading(' ');
  797. //parse the text.
  798. rawText.Replace(" ", "+");
  799. rawText.Replace("\"", "%22");
  800. rawText.Replace("#", "%23");
  801. rawText.Replace("&", "%26");
  802. rawText.Replace("'", "%27");
  803. rawText.Replace("`", "%27");
  804. rawText.Replace("(", "%28");
  805. rawText.Replace(")", "%29");
  806. rawText.Replace("*", "%2a");
  807. rawText.Replace(",", "%2c");
  808. rawText.Replace("-", "%2d");
  809. rawText.Replace(".", "%2e");
  810. rawText.Replace("/", "%2f");
  811. rawText.Replace(":", "%3a");
  812. rawText.Replace(";", "%3b");
  813. rawText.Replace("?", "%3f");
  814. rawText.Replace("@", "%40");
  815. rawText.Replace("[", "%5b");
  816. rawText.Replace("\\", "%5c");
  817. rawText.Replace("]", "%5d");
  818. rawText.Replace("^", "%5e");
  819. rawText.Replace("_", "%5f");
  820. rawText.Replace("{", "%7b");
  821. rawText.Replace("|", "%7c");
  822. rawText.Replace("}", "%7d");
  823. rawText.Replace("~", "%7e");
  824. rawText.Replace("=", "%61");
  825. rawText.Replace("\"", "%93");
  826. rawText.Replace("\"", "%94");
  827. rawText.Replace("-", "%97");
  828. if ( rawText.Length() )
  829. {
  830. //only send string if it has characters.
  831. idAsyncNetwork::client.SendBugreport(rawText.c_str());
  832. }
  833. continue;
  834. }
  835. if ( !idStr::Icmp( cmd, "inetConnect" ) ) {
  836. const char *s = guiMainMenu->State().GetString( "inetGame" );
  837. if ( !s || s[0] == 0 ) {
  838. // don't put the menu away if there isn't a valid selection
  839. continue;
  840. }
  841. cmdSystem->BufferCommandText( CMD_EXEC_NOW, va( "connect %s", s ) );
  842. return;
  843. }
  844. if ( !idStr::Icmp( cmd, "startMultiplayer" ) ) {
  845. int dedicated = guiActive->State().GetInt( "dedicated" );
  846. cvarSystem->SetCVarBool( "net_LANServer", guiActive->State().GetBool( "server_type" ) );
  847. if ( gui_configServerRate.GetInteger() > 0 ) {
  848. // guess the best rate for upstream, number of internet clients
  849. if ( gui_configServerRate.GetInteger() == 5 || cvarSystem->GetCVarBool( "net_LANServer" ) ) {
  850. cvarSystem->SetCVarInteger( "net_serverMaxClientRate", 25600 );
  851. } else {
  852. // internet players
  853. int n_clients = cvarSystem->GetCVarInteger( "si_maxPlayers" );
  854. if ( !dedicated ) {
  855. n_clients--;
  856. }
  857. int maxclients = 0;
  858. switch ( gui_configServerRate.GetInteger() ) {
  859. case 1:
  860. // 128 kbits
  861. cvarSystem->SetCVarInteger( "net_serverMaxClientRate", 8000 );
  862. maxclients = 2;
  863. break;
  864. case 2:
  865. // 256 kbits
  866. cvarSystem->SetCVarInteger( "net_serverMaxClientRate", 9500 );
  867. maxclients = 3;
  868. break;
  869. case 3:
  870. // 384 kbits
  871. cvarSystem->SetCVarInteger( "net_serverMaxClientRate", 10500 );
  872. maxclients = 4;
  873. break;
  874. case 4:
  875. // 512 and above..
  876. cvarSystem->SetCVarInteger( "net_serverMaxClientRate", 14000 );
  877. maxclients = 4;
  878. break;
  879. }
  880. if ( n_clients > maxclients ) {
  881. if ( MessageBox( MSG_OKCANCEL, va( common->GetLanguageDict()->GetString( "#str_04315" ), dedicated ? maxclients : Min( 8, maxclients + 1 ) ), common->GetLanguageDict()->GetString( "#str_04316" ), true, "OK" )[ 0 ] == '\0' ) {
  882. continue;
  883. }
  884. cvarSystem->SetCVarInteger( "si_maxPlayers", dedicated ? maxclients : Min( 8, maxclients + 1 ) );
  885. }
  886. }
  887. }
  888. if ( !dedicated && !cvarSystem->GetCVarBool( "net_LANServer" ) && cvarSystem->GetCVarInteger("si_maxPlayers") > 4 ) {
  889. // "Dedicated server mode is recommended for internet servers with more than 4 players. Continue in listen mode?"
  890. if ( !MessageBox( MSG_YESNO, common->GetLanguageDict()->GetString ( "#str_00100625" ), common->GetLanguageDict()->GetString ( "#str_00100626" ), true, "yes" )[ 0 ] ) {
  891. continue;
  892. }
  893. }
  894. if ( dedicated ) {
  895. cvarSystem->SetCVarInteger( "net_serverDedicated", 1 );
  896. } else {
  897. cvarSystem->SetCVarInteger( "net_serverDedicated", 0 );
  898. }
  899. ExitMenu();
  900. // may trigger a reloadEngine - APPEND
  901. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "SpawnServer\n" );
  902. return;
  903. }
  904. if ( !idStr::Icmp( cmd, "mpSkin")) {
  905. idStr skin;
  906. if ( args.Argc() - icmd >= 1 ) {
  907. skin = args.Argv( icmd++ );
  908. cvarSystem->SetCVarString( "ui_skin", skin );
  909. SetMainMenuSkin();
  910. }
  911. continue;
  912. }
  913. if ( !idStr::Icmp( cmd, "close" ) ) {
  914. // if we aren't in a game, the menu can't be closed
  915. if ( mapSpawned ) {
  916. ExitMenu();
  917. }
  918. continue;
  919. }
  920. if ( !idStr::Icmp( cmd, "resetdefaults" ) ) {
  921. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "exec default.cfg" );
  922. guiMainMenu->SetKeyBindingNames();
  923. continue;
  924. }
  925. if ( !idStr::Icmp( cmd, "bind" ) ) {
  926. if ( args.Argc() - icmd >= 2 ) {
  927. int key = atoi( args.Argv( icmd++ ) );
  928. idStr bind = args.Argv( icmd++ );
  929. if ( idKeyInput::NumBinds( bind ) >= 2 && !idKeyInput::KeyIsBoundTo( key, bind ) ) {
  930. idKeyInput::UnbindBinding( bind );
  931. }
  932. idKeyInput::SetBinding( key, bind );
  933. guiMainMenu->SetKeyBindingNames();
  934. }
  935. continue;
  936. }
  937. if ( !idStr::Icmp( cmd, "play" ) ) {
  938. if ( args.Argc() - icmd >= 1 ) {
  939. idStr snd = args.Argv( icmd++ );
  940. int channel = 1;
  941. if ( snd.Length() == 1 ) {
  942. channel = atoi( snd );
  943. snd = args.Argv( icmd++ );
  944. }
  945. menuSoundWorld->PlayShaderDirectly( snd, channel );
  946. }
  947. continue;
  948. }
  949. if ( !idStr::Icmp( cmd, "music" ) ) {
  950. if ( args.Argc() - icmd >= 1 ) {
  951. idStr snd = args.Argv( icmd++ );
  952. menuSoundWorld->PlayShaderDirectly( snd, 2 );
  953. }
  954. continue;
  955. }
  956. // triggered from mainmenu or mpmain
  957. if ( !idStr::Icmp( cmd, "sound" ) ) {
  958. idStr vcmd;
  959. if ( args.Argc() - icmd >= 1 ) {
  960. vcmd = args.Argv( icmd++ );
  961. }
  962. if ( !vcmd.Length() || !vcmd.Icmp( "speakers" ) ) {
  963. int old = cvarSystem->GetCVarInteger( "s_numberOfSpeakers" );
  964. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "s_restart\n" );
  965. if ( old != cvarSystem->GetCVarInteger( "s_numberOfSpeakers" ) ) {
  966. #ifdef _WIN32
  967. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_04142" ), common->GetLanguageDict()->GetString( "#str_04141" ), true );
  968. #else
  969. // a message that doesn't mention the windows control panel
  970. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_07230" ), common->GetLanguageDict()->GetString( "#str_04141" ), true );
  971. #endif
  972. }
  973. }
  974. if ( !vcmd.Icmp( "eax" ) ) {
  975. if ( cvarSystem->GetCVarBool( "s_useEAXReverb" ) ) {
  976. #ifndef __linux__
  977. int eax = soundSystem->IsEAXAvailable();
  978. switch ( eax ) {
  979. case 2:
  980. // OpenAL subsystem load failed
  981. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_07238" ), common->GetLanguageDict()->GetString( "#str_07231" ), true );
  982. break;
  983. #else
  984. int efx = soundSystem->IsEFXAvailable();
  985. switch ( efx ) {
  986. #endif
  987. case 1:
  988. // when you restart
  989. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_04137" ), common->GetLanguageDict()->GetString( "#str_07231" ), true );
  990. break;
  991. case -1:
  992. cvarSystem->SetCVarBool( "s_useEAXReverb", false );
  993. // disabled
  994. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_07233" ), common->GetLanguageDict()->GetString( "#str_07231" ), true );
  995. break;
  996. case 0:
  997. cvarSystem->SetCVarBool( "s_useEAXReverb", false );
  998. // not available
  999. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_07232" ), common->GetLanguageDict()->GetString( "#str_07231" ), true );
  1000. break;
  1001. }
  1002. } else {
  1003. #ifndef __linux__
  1004. // also turn off OpenAL so we fully go back to legacy mixer
  1005. cvarSystem->SetCVarBool( "s_useOpenAL", false );
  1006. #endif
  1007. // when you restart
  1008. MessageBox( MSG_OK, common->GetLanguageDict()->GetString( "#str_04137" ), common->GetLanguageDict()->GetString( "#str_07231" ), true );
  1009. }
  1010. }
  1011. if ( !vcmd.Icmp( "drivar" ) ) {
  1012. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "s_restart\n" );
  1013. }
  1014. continue;
  1015. }
  1016. if ( !idStr::Icmp( cmd, "video" ) ) {
  1017. idStr vcmd;
  1018. if ( args.Argc() - icmd >= 1 ) {
  1019. vcmd = args.Argv( icmd++ );
  1020. }
  1021. int oldSpec = com_machineSpec.GetInteger();
  1022. if ( idStr::Icmp( vcmd, "low" ) == 0 ) {
  1023. com_machineSpec.SetInteger( 0 );
  1024. } else if ( idStr::Icmp( vcmd, "medium" ) == 0 ) {
  1025. com_machineSpec.SetInteger( 1 );
  1026. } else if ( idStr::Icmp( vcmd, "high" ) == 0 ) {
  1027. com_machineSpec.SetInteger( 2 );
  1028. } else if ( idStr::Icmp( vcmd, "ultra" ) == 0 ) {
  1029. com_machineSpec.SetInteger( 3 );
  1030. } else if ( idStr::Icmp( vcmd, "recommended" ) == 0 ) {
  1031. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "setMachineSpec\n" );
  1032. }
  1033. if ( oldSpec != com_machineSpec.GetInteger() ) {
  1034. guiActive->SetStateInt( "com_machineSpec", com_machineSpec.GetInteger() );
  1035. guiActive->StateChanged( com_frameTime );
  1036. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "execMachineSpec\n" );
  1037. }
  1038. if ( idStr::Icmp( vcmd, "restart" ) == 0) {
  1039. guiActive->HandleNamedEvent( "cvar write render" );
  1040. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart\n" );
  1041. }
  1042. continue;
  1043. }
  1044. if ( !idStr::Icmp( cmd, "clearBind" ) ) {
  1045. if ( args.Argc() - icmd >= 1 ) {
  1046. idKeyInput::UnbindBinding( args.Argv( icmd++ ) );
  1047. guiMainMenu->SetKeyBindingNames();
  1048. }
  1049. continue;
  1050. }
  1051. // FIXME: obsolete
  1052. if ( !idStr::Icmp( cmd, "chatdone" ) ) {
  1053. idStr temp = guiActive->State().GetString( "chattext" );
  1054. temp += "\r";
  1055. guiActive->SetStateString( "chattext", "" );
  1056. continue;
  1057. }
  1058. if ( !idStr::Icmp ( cmd, "exec" ) ) {
  1059. //Backup the language so we can restore it after defaults.
  1060. idStr lang = cvarSystem->GetCVarString("sys_lang");
  1061. cmdSystem->BufferCommandText( CMD_EXEC_NOW, args.Argv( icmd++ ) );
  1062. if ( idStr::Icmp( "cvar_restart", args.Argv( icmd - 1 ) ) == 0 ) {
  1063. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "exec default.cfg" );
  1064. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "setMachineSpec\n" );
  1065. //Make sure that any r_brightness changes take effect
  1066. float bright = cvarSystem->GetCVarFloat("r_brightness");
  1067. cvarSystem->SetCVarFloat("r_brightness", 0.0f);
  1068. cvarSystem->SetCVarFloat("r_brightness", bright);
  1069. //Force user info modified after a reset to defaults
  1070. cvarSystem->SetModifiedFlags(CVAR_USERINFO);
  1071. guiActive->SetStateInt( "com_machineSpec", com_machineSpec.GetInteger() );
  1072. //Restore the language
  1073. cvarSystem->SetCVarString("sys_lang", lang);
  1074. }
  1075. continue;
  1076. }
  1077. if ( !idStr::Icmp ( cmd, "loadBinds" ) ) {
  1078. guiMainMenu->SetKeyBindingNames();
  1079. continue;
  1080. }
  1081. if ( !idStr::Icmp( cmd, "systemCvars" ) ) {
  1082. guiActive->HandleNamedEvent( "cvar read render" );
  1083. guiActive->HandleNamedEvent( "cvar read sound" );
  1084. continue;
  1085. }
  1086. if ( !idStr::Icmp( cmd, "SetCDKey" ) ) {
  1087. // we can't do this from inside the HandleMainMenuCommands code, otherwise the message box stuff gets confused
  1088. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "promptKey\n" );
  1089. continue;
  1090. }
  1091. if ( !idStr::Icmp( cmd, "CheckUpdate" ) ) {
  1092. idAsyncNetwork::client.SendVersionCheck();
  1093. continue;
  1094. }
  1095. if ( !idStr::Icmp( cmd, "CheckUpdate2" ) ) {
  1096. idAsyncNetwork::client.SendVersionCheck( true );
  1097. continue;
  1098. }
  1099. if ( !idStr::Icmp( cmd, "checkKeys" ) ) {
  1100. #if ID_ENFORCE_KEY
  1101. // not a strict check so you silently auth in the background without bugging the user
  1102. if ( !session->CDKeysAreValid( false ) ) {
  1103. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "promptKey force" );
  1104. cmdSystem->ExecuteCommandBuffer();
  1105. }
  1106. #endif
  1107. continue;
  1108. }
  1109. // triggered from mainmenu or mpmain
  1110. if ( !idStr::Icmp( cmd, "punkbuster" ) ) {
  1111. idStr vcmd;
  1112. if ( args.Argc() - icmd >= 1 ) {
  1113. vcmd = args.Argv( icmd++ );
  1114. }
  1115. // filtering PB based on enabled/disabled
  1116. idAsyncNetwork::client.serverList.ApplyFilter( );
  1117. SetPbMenuGuiVars();
  1118. continue;
  1119. }
  1120. }
  1121. }
  1122. /*
  1123. ==============
  1124. idSessionLocal::HandleChatMenuCommands
  1125. Executes any commands returned by the gui
  1126. ==============
  1127. */
  1128. void idSessionLocal::HandleChatMenuCommands( const char *menuCommand ) {
  1129. // execute the command from the menu
  1130. int i;
  1131. idCmdArgs args;
  1132. args.TokenizeString( menuCommand, false );
  1133. for ( i = 0; i < args.Argc(); ) {
  1134. const char *cmd = args.Argv( i++ );
  1135. if ( idStr::Icmp( cmd, "chatactive" ) == 0 ) {
  1136. //chat.chatMode = CHAT_GLOBAL;
  1137. continue;
  1138. }
  1139. if ( idStr::Icmp( cmd, "chatabort" ) == 0 ) {
  1140. //chat.chatMode = CHAT_NONE;
  1141. continue;
  1142. }
  1143. if ( idStr::Icmp( cmd, "netready" ) == 0 ) {
  1144. bool b = cvarSystem->GetCVarBool( "ui_ready" );
  1145. cvarSystem->SetCVarBool( "ui_ready", !b );
  1146. continue;
  1147. }
  1148. if ( idStr::Icmp( cmd, "netstart" ) == 0 ) {
  1149. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "netcommand start\n" );
  1150. continue;
  1151. }
  1152. }
  1153. }
  1154. /*
  1155. ==============
  1156. idSessionLocal::HandleInGameCommands
  1157. Executes any commands returned by the gui
  1158. ==============
  1159. */
  1160. void idSessionLocal::HandleInGameCommands( const char *menuCommand ) {
  1161. // execute the command from the menu
  1162. idCmdArgs args;
  1163. args.TokenizeString( menuCommand, false );
  1164. const char *cmd = args.Argv( 0 );
  1165. if ( !idStr::Icmp( cmd, "close" ) || !idStr::Icmp( cmd, "closeAndGet" ) )
  1166. {
  1167. if ( guiActive )
  1168. {
  1169. sysEvent_t ev;
  1170. ev.evType = SE_NONE;
  1171. //const char *cmd1;
  1172. //cmd1 = guiActive->HandleEvent( &ev, com_frameTime );
  1173. guiActive->HandleEvent( &ev, com_frameTime );
  1174. guiActive->Activate( false, com_frameTime );
  1175. guiActive = NULL;
  1176. }
  1177. //BC Close the deck and return to normal operation.
  1178. guiActive = NULL;
  1179. this->SetGUI(NULL, NULL);
  1180. guiTest = NULL;
  1181. cvarSystem->SetCVarBool( "ui_chat", true );
  1182. cvarSystem->SetCVarBool("deckActive", true, 0);
  1183. if (!idStr::Icmp( cmd, "closeAndGet" ))
  1184. {
  1185. //player wants to close the deck and grab it up.
  1186. cvarSystem->SetCVarBool("closeAndGet", true);
  1187. }
  1188. }
  1189. else if ( !idStr::Icmp( cmd, "stickyclosecancel" ))
  1190. {
  1191. cvarSystem->SetCVarBool("stickyCloseCancel", true);
  1192. }
  1193. else if ( !idStr::Icmp( cmd, "stickycloseconfirm" ))
  1194. {
  1195. cvarSystem->SetCVarBool("stickyCloseConfirm", true);
  1196. }
  1197. }
  1198. /*
  1199. ==============
  1200. idSessionLocal::DispatchCommand
  1201. ==============
  1202. */
  1203. void idSessionLocal::DispatchCommand( idUserInterface *gui, const char *menuCommand, bool doIngame ) {
  1204. if ( !gui ) {
  1205. gui = guiActive;
  1206. }
  1207. if ( gui == guiMainMenu ) {
  1208. HandleMainMenuCommands( menuCommand );
  1209. return;
  1210. } else if ( gui == guiIntro) {
  1211. HandleIntroMenuCommands( menuCommand );
  1212. } else if ( gui == guiMsg ) {
  1213. HandleMsgCommands( menuCommand );
  1214. } else if ( gui == guiTakeNotes ) {
  1215. HandleNoteCommands( menuCommand );
  1216. } else if ( gui == guiRestartMenu ) {
  1217. HandleRestartMenuCommands( menuCommand );
  1218. } else if ( game && guiActive && guiActive->State().GetBool( "gameDraw" ) ) {
  1219. const char *cmd = game->HandleGuiCommands( menuCommand );
  1220. if ( !cmd ) {
  1221. guiActive = NULL;
  1222. } else if ( idStr::Icmp( cmd, "main" ) == 0 ) {
  1223. StartMenu();
  1224. } else if ( strstr( cmd, "sound " ) == cmd ) {
  1225. // pipe the GUI sound commands not handled by the game to the main menu code
  1226. HandleMainMenuCommands( cmd );
  1227. }
  1228. } else if ( guiHandle ) {
  1229. if ( (*guiHandle)( menuCommand ) ) {
  1230. return;
  1231. }
  1232. } else if ( !doIngame ) {
  1233. common->DPrintf( "idSessionLocal::DispatchCommand: no dispatch found for command '%s'\n", menuCommand );
  1234. }
  1235. if ( doIngame ) {
  1236. HandleInGameCommands( menuCommand );
  1237. }
  1238. }
  1239. /*
  1240. ==============
  1241. idSessionLocal::MenuEvent
  1242. Executes any commands returned by the gui
  1243. ==============
  1244. */
  1245. void idSessionLocal::MenuEvent( const sysEvent_t *event ) {
  1246. const char *menuCommand;
  1247. if ( guiActive == NULL ) {
  1248. return;
  1249. }
  1250. menuCommand = guiActive->HandleEvent( event, com_frameTime );
  1251. if ( !menuCommand || !menuCommand[0] ) {
  1252. // If the menu didn't handle the event, and it's a key down event for an F key, run the bind
  1253. if ( event->evType == SE_KEY && event->evValue2 == 1 && event->evValue >= K_F1 && event->evValue <= K_F12 ) {
  1254. idKeyInput::ExecKeyBinding( event->evValue );
  1255. }
  1256. return;
  1257. }
  1258. DispatchCommand( guiActive, menuCommand );
  1259. }
  1260. /*
  1261. =================
  1262. idSessionLocal::GuiFrameEvents
  1263. =================
  1264. */
  1265. void idSessionLocal::GuiFrameEvents() {
  1266. const char *cmd;
  1267. sysEvent_t ev;
  1268. idUserInterface *gui;
  1269. // stop generating move and button commands when a local console or menu is active
  1270. // running here so SP, async networking and no game all go through it
  1271. if ( console->Active() || guiActive ) {
  1272. usercmdGen->InhibitUsercmd( INHIBIT_SESSION, true );
  1273. } else {
  1274. usercmdGen->InhibitUsercmd( INHIBIT_SESSION, false );
  1275. }
  1276. if ( guiTest ) {
  1277. gui = guiTest;
  1278. } else if ( guiActive ) {
  1279. gui = guiActive;
  1280. } else {
  1281. return;
  1282. }
  1283. memset( &ev, 0, sizeof( ev ) );
  1284. ev.evType = SE_NONE;
  1285. cmd = gui->HandleEvent( &ev, com_frameTime );
  1286. if ( cmd && cmd[0] ) {
  1287. DispatchCommand( guiActive, cmd );
  1288. }
  1289. }
  1290. /*
  1291. =================
  1292. idSessionLocal::BoxDialogSanityCheck
  1293. =================
  1294. */
  1295. bool idSessionLocal::BoxDialogSanityCheck( void ) {
  1296. if ( !common->IsInitialized() ) {
  1297. common->DPrintf( "message box sanity check: !common->IsInitialized()\n" );
  1298. return false;
  1299. }
  1300. if ( !guiMsg ) {
  1301. return false;
  1302. }
  1303. if ( guiMsgRestore ) {
  1304. common->DPrintf( "message box sanity check: recursed\n" );
  1305. return false;
  1306. }
  1307. if ( cvarSystem->GetCVarInteger( "net_serverDedicated" ) ) {
  1308. common->DPrintf( "message box sanity check: not compatible with dedicated server\n" );
  1309. return false;
  1310. }
  1311. return true;
  1312. }
  1313. /*
  1314. =================
  1315. idSessionLocal::MessageBox
  1316. =================
  1317. */
  1318. const char* idSessionLocal::MessageBox( msgBoxType_t type, const char *message, const char *title, bool wait, const char *fire_yes, const char *fire_no, bool network ) {
  1319. common->DPrintf( "MessageBox: %s - %s\n", title ? title : "", message ? message : "" );
  1320. if ( !BoxDialogSanityCheck() ) {
  1321. return NULL;
  1322. }
  1323. guiMsg->SetStateString( "title", title ? title : "" );
  1324. guiMsg->SetStateString( "message", message ? message : "" );
  1325. if ( type == MSG_WAIT ) {
  1326. guiMsg->SetStateString( "visible_msgbox", "0" );
  1327. guiMsg->SetStateString( "visible_waitbox", "1" );
  1328. } else {
  1329. guiMsg->SetStateString( "visible_msgbox", "1" );
  1330. guiMsg->SetStateString( "visible_waitbox", "0" );
  1331. }
  1332. guiMsg->SetStateString( "visible_entry", "0" );
  1333. guiMsg->SetStateString( "visible_cdkey", "0" );
  1334. switch ( type ) {
  1335. case MSG_INFO:
  1336. guiMsg->SetStateString( "mid", "" );
  1337. guiMsg->SetStateString( "visible_mid", "0" );
  1338. guiMsg->SetStateString( "visible_left", "0" );
  1339. guiMsg->SetStateString( "visible_right", "0" );
  1340. break;
  1341. case MSG_OK:
  1342. guiMsg->SetStateString( "mid", common->GetLanguageDict()->GetString( "#str_04339" ) );
  1343. guiMsg->SetStateString( "visible_mid", "1" );
  1344. guiMsg->SetStateString( "visible_left", "0" );
  1345. guiMsg->SetStateString( "visible_right", "0" );
  1346. break;
  1347. case MSG_ABORT:
  1348. guiMsg->SetStateString( "mid", common->GetLanguageDict()->GetString( "#str_04340" ) );
  1349. guiMsg->SetStateString( "visible_mid", "1" );
  1350. guiMsg->SetStateString( "visible_left", "0" );
  1351. guiMsg->SetStateString( "visible_right", "0" );
  1352. break;
  1353. case MSG_OKCANCEL:
  1354. guiMsg->SetStateString( "left", common->GetLanguageDict()->GetString( "#str_04339" ) );
  1355. guiMsg->SetStateString( "right", common->GetLanguageDict()->GetString( "#str_04340" ) );
  1356. guiMsg->SetStateString( "visible_mid", "0" );
  1357. guiMsg->SetStateString( "visible_left", "1" );
  1358. guiMsg->SetStateString( "visible_right", "1" );
  1359. break;
  1360. case MSG_YESNO:
  1361. guiMsg->SetStateString( "left", common->GetLanguageDict()->GetString( "#str_04341" ) );
  1362. guiMsg->SetStateString( "right", common->GetLanguageDict()->GetString( "#str_04342" ) );
  1363. guiMsg->SetStateString( "visible_mid", "0" );
  1364. guiMsg->SetStateString( "visible_left", "1" );
  1365. guiMsg->SetStateString( "visible_right", "1" );
  1366. break;
  1367. case MSG_PROMPT:
  1368. guiMsg->SetStateString( "left", common->GetLanguageDict()->GetString( "#str_04339" ) );
  1369. guiMsg->SetStateString( "right", common->GetLanguageDict()->GetString( "#str_04340" ) );
  1370. guiMsg->SetStateString( "visible_mid", "0" );
  1371. guiMsg->SetStateString( "visible_left", "1" );
  1372. guiMsg->SetStateString( "visible_right", "1" );
  1373. guiMsg->SetStateString( "visible_entry", "1" );
  1374. guiMsg->HandleNamedEvent( "Prompt" );
  1375. break;
  1376. case MSG_CDKEY:
  1377. guiMsg->SetStateString( "left", common->GetLanguageDict()->GetString( "#str_04339" ) );
  1378. guiMsg->SetStateString( "right", common->GetLanguageDict()->GetString( "#str_04340" ) );
  1379. guiMsg->SetStateString( "visible_msgbox", "0" );
  1380. guiMsg->SetStateString( "visible_cdkey", "1" );
  1381. guiMsg->SetStateString( "visible_hasxp", fileSystem->HasD3XP() ? "1" : "0" );
  1382. // the current cdkey / xpkey values may have bad/random data in them
  1383. // it's best to avoid printing them completely, unless the key is good
  1384. if ( cdkey_state == CDKEY_OK ) {
  1385. guiMsg->SetStateString( "str_cdkey", cdkey );
  1386. guiMsg->SetStateString( "visible_cdchk", "0" );
  1387. } else {
  1388. guiMsg->SetStateString( "str_cdkey", "" );
  1389. guiMsg->SetStateString( "visible_cdchk", "1" );
  1390. }
  1391. guiMsg->SetStateString( "str_cdchk", "" );
  1392. if ( xpkey_state == CDKEY_OK ) {
  1393. guiMsg->SetStateString( "str_xpkey", xpkey );
  1394. guiMsg->SetStateString( "visible_xpchk", "0" );
  1395. } else {
  1396. guiMsg->SetStateString( "str_xpkey", "" );
  1397. guiMsg->SetStateString( "visible_xpchk", "1" );
  1398. }
  1399. guiMsg->SetStateString( "str_xpchk", "" );
  1400. guiMsg->HandleNamedEvent( "CDKey" );
  1401. break;
  1402. case MSG_WAIT:
  1403. break;
  1404. default:
  1405. common->Printf( "idSessionLocal::MessageBox: unknown msg box type\n" );
  1406. }
  1407. msgFireBack[ 0 ] = fire_yes ? fire_yes : "";
  1408. msgFireBack[ 1 ] = fire_no ? fire_no : "";
  1409. guiMsgRestore = guiActive;
  1410. guiActive = guiMsg;
  1411. guiMsg->SetCursor( 325, 290 );
  1412. guiActive->Activate( true, com_frameTime );
  1413. msgRunning = true;
  1414. msgRetIndex = -1;
  1415. if ( wait ) {
  1416. // play one frame ignoring events so we don't get confused by parasite button releases
  1417. msgIgnoreButtons = true;
  1418. common->GUIFrame( true, network );
  1419. msgIgnoreButtons = false;
  1420. while ( msgRunning ) {
  1421. common->GUIFrame( true, network );
  1422. }
  1423. if ( msgRetIndex < 0 ) {
  1424. // MSG_WAIT and other StopBox calls
  1425. return NULL;
  1426. }
  1427. if ( type == MSG_PROMPT ) {
  1428. if ( msgRetIndex == 0 ) {
  1429. guiMsg->State().GetString( "str_entry", "", msgFireBack[ 0 ] );
  1430. return msgFireBack[ 0 ].c_str();
  1431. } else {
  1432. return NULL;
  1433. }
  1434. } else if ( type == MSG_CDKEY ) {
  1435. if ( msgRetIndex == 0 ) {
  1436. // the visible_ values distinguish looking at a valid key, or editing it
  1437. sprintf( msgFireBack[ 0 ], "%1s;%16s;%2s;%1s;%16s;%2s",
  1438. guiMsg->State().GetString( "visible_cdchk" ),
  1439. guiMsg->State().GetString( "str_cdkey" ),
  1440. guiMsg->State().GetString( "str_cdchk" ),
  1441. guiMsg->State().GetString( "visible_xpchk" ),
  1442. guiMsg->State().GetString( "str_xpkey" ),
  1443. guiMsg->State().GetString( "str_xpchk" ) );
  1444. return msgFireBack[ 0 ].c_str();
  1445. } else {
  1446. return NULL;
  1447. }
  1448. } else {
  1449. return msgFireBack[ msgRetIndex ].c_str();
  1450. }
  1451. }
  1452. return NULL;
  1453. }
  1454. /*
  1455. =================
  1456. idSessionLocal::DownloadProgressBox
  1457. =================
  1458. */
  1459. void idSessionLocal::DownloadProgressBox( backgroundDownload_t *bgl, const char *title, int progress_start, int progress_end ) {
  1460. int dlnow = 0, dltotal = 0;
  1461. int startTime = Sys_Milliseconds();
  1462. int lapsed;
  1463. idStr sNow, sTotal, sBW, sETA, sMsg;
  1464. if ( !BoxDialogSanityCheck() ) {
  1465. return;
  1466. }
  1467. guiMsg->SetStateString( "visible_msgbox", "1" );
  1468. guiMsg->SetStateString( "visible_waitbox", "0" );
  1469. guiMsg->SetStateString( "visible_entry", "0" );
  1470. guiMsg->SetStateString( "visible_cdkey", "0" );
  1471. guiMsg->SetStateString( "mid", "Cancel" );
  1472. guiMsg->SetStateString( "visible_mid", "1" );
  1473. guiMsg->SetStateString( "visible_left", "0" );
  1474. guiMsg->SetStateString( "visible_right", "0" );
  1475. guiMsg->SetStateString( "title", title );
  1476. guiMsg->SetStateString( "message", "Connecting.." );
  1477. guiMsgRestore = guiActive;
  1478. guiActive = guiMsg;
  1479. msgRunning = true;
  1480. while ( 1 ) {
  1481. while ( msgRunning ) {
  1482. common->GUIFrame( true, false );
  1483. if ( bgl->completed ) {
  1484. guiActive = guiMsgRestore;
  1485. guiMsgRestore = NULL;
  1486. return;
  1487. } else if ( bgl->url.dltotal != dltotal || bgl->url.dlnow != dlnow ) {
  1488. dltotal = bgl->url.dltotal;
  1489. dlnow = bgl->url.dlnow;
  1490. lapsed = Sys_Milliseconds() - startTime;
  1491. sNow.BestUnit( "%.2f", dlnow, MEASURE_SIZE );
  1492. if ( lapsed > 2000 ) {
  1493. sBW.BestUnit( "%.1f", ( 1000.0f * dlnow ) / lapsed, MEASURE_BANDWIDTH );
  1494. } else {
  1495. sBW = "-- KB/s";
  1496. }
  1497. if ( dltotal ) {
  1498. sTotal.BestUnit( "%.2f", dltotal, MEASURE_SIZE );
  1499. if ( lapsed < 2000 ) {
  1500. sprintf( sMsg, "%s / %s", sNow.c_str(), sTotal.c_str() );
  1501. } else {
  1502. sprintf( sETA, "%.0f sec", ( (float)dltotal / (float)dlnow - 1.0f ) * lapsed / 1000 );
  1503. sprintf( sMsg, "%s / %s ( %s - %s )", sNow.c_str(), sTotal.c_str(), sBW.c_str(), sETA.c_str() );
  1504. }
  1505. } else {
  1506. if ( lapsed < 2000 ) {
  1507. sMsg = sNow;
  1508. } else {
  1509. sprintf( sMsg, "%s - %s", sNow.c_str(), sBW.c_str() );
  1510. }
  1511. }
  1512. if ( dltotal ) {
  1513. guiMsg->SetStateString( "progress", va( "%d", progress_start + dlnow * ( progress_end - progress_start ) / dltotal ) );
  1514. } else {
  1515. guiMsg->SetStateString( "progress", "0" );
  1516. }
  1517. guiMsg->SetStateString( "message", sMsg.c_str() );
  1518. }
  1519. }
  1520. // abort was used - tell the downloader and wait till final stop
  1521. bgl->url.status = DL_ABORTING;
  1522. guiMsg->SetStateString( "title", "Aborting.." );
  1523. guiMsg->SetStateString( "visible_mid", "0" );
  1524. // continue looping
  1525. guiMsgRestore = guiActive;
  1526. guiActive = guiMsg;
  1527. msgRunning = true;
  1528. }
  1529. }
  1530. /*
  1531. =================
  1532. idSessionLocal::StopBox
  1533. =================
  1534. */
  1535. void idSessionLocal::StopBox() {
  1536. if ( guiActive == guiMsg ) {
  1537. HandleMsgCommands( "stop" );
  1538. }
  1539. }
  1540. /*
  1541. =================
  1542. idSessionLocal::HandleMsgCommands
  1543. =================
  1544. */
  1545. void idSessionLocal::HandleMsgCommands( const char *menuCommand ) {
  1546. assert( guiActive == guiMsg );
  1547. // "stop" works even on first frame
  1548. if ( idStr::Icmp( menuCommand, "stop" ) == 0 ) {
  1549. // force hiding the current dialog
  1550. guiActive = guiMsgRestore;
  1551. guiMsgRestore = NULL;
  1552. msgRunning = false;
  1553. msgRetIndex = -1;
  1554. }
  1555. if ( msgIgnoreButtons ) {
  1556. common->DPrintf( "MessageBox HandleMsgCommands 1st frame ignore\n" );
  1557. return;
  1558. }
  1559. if ( idStr::Icmp( menuCommand, "mid" ) == 0 || idStr::Icmp( menuCommand, "left" ) == 0 ) {
  1560. guiActive = guiMsgRestore;
  1561. guiMsgRestore = NULL;
  1562. msgRunning = false;
  1563. msgRetIndex = 0;
  1564. DispatchCommand( guiActive, msgFireBack[ 0 ].c_str() );
  1565. } else if ( idStr::Icmp( menuCommand, "right" ) == 0 ) {
  1566. guiActive = guiMsgRestore;
  1567. guiMsgRestore = NULL;
  1568. msgRunning = false;
  1569. msgRetIndex = 1;
  1570. DispatchCommand( guiActive, msgFireBack[ 1 ].c_str() );
  1571. }
  1572. }
  1573. /*
  1574. =================
  1575. idSessionLocal::HandleNoteCommands
  1576. =================
  1577. */
  1578. #define NOTEDATFILE "C:/notenumber.dat"
  1579. void idSessionLocal::HandleNoteCommands( const char *menuCommand ) {
  1580. guiActive = NULL;
  1581. if ( idStr::Icmp( menuCommand, "note" ) == 0 && mapSpawned ) {
  1582. idFile *file = NULL;
  1583. for ( int tries = 0; tries < 10; tries++ ) {
  1584. file = fileSystem->OpenExplicitFileRead( NOTEDATFILE );
  1585. if ( file != NULL ) {
  1586. break;
  1587. }
  1588. Sys_Sleep( 500 );
  1589. }
  1590. int noteNumber = 1000;
  1591. if ( file ) {
  1592. file->Read( &noteNumber, 4 );
  1593. fileSystem->CloseFile( file );
  1594. }
  1595. int i;
  1596. idStr str, noteNum, shotName, workName, fileName = "viewnotes/";
  1597. idStrList fileList;
  1598. const char *severity = NULL;
  1599. const char *p = guiTakeNotes->State().GetString( "notefile" );
  1600. if ( p == NULL || *p == '\0' ) {
  1601. p = cvarSystem->GetCVarString( "ui_name" );
  1602. }
  1603. bool extended = guiTakeNotes->State().GetBool( "extended" );
  1604. if ( extended ) {
  1605. if ( guiTakeNotes->State().GetInt( "severity" ) == 1 ) {
  1606. severity = "WishList_Viewnotes/";
  1607. } else {
  1608. severity = "MustFix_Viewnotes/";
  1609. }
  1610. fileName += severity;
  1611. const idDecl *mapDecl = declManager->FindType(DECL_ENTITYDEF, mapSpawnData.serverInfo.GetString( "si_map" ), false );
  1612. const idDeclEntityDef *mapInfo = static_cast<const idDeclEntityDef *>(mapDecl);
  1613. if ( mapInfo ) {
  1614. fileName += mapInfo->dict.GetString( "devname" );
  1615. } else {
  1616. fileName += mapSpawnData.serverInfo.GetString( "si_map" );
  1617. fileName.StripFileExtension();
  1618. }
  1619. int count = guiTakeNotes->State().GetInt( "person_numsel" );
  1620. if ( count == 0 ) {
  1621. fileList.Append( fileName + "/Nobody" );
  1622. } else {
  1623. for ( i = 0; i < count; i++ ) {
  1624. int person = guiTakeNotes->State().GetInt( va( "person_sel_%i", i ) );
  1625. workName = fileName + "/";
  1626. workName += guiTakeNotes->State().GetString( va( "person_item_%i", person ), "Nobody" );
  1627. fileList.Append( workName );
  1628. }
  1629. }
  1630. } else {
  1631. fileName += "maps/";
  1632. fileName += mapSpawnData.serverInfo.GetString( "si_map" );
  1633. fileName.StripFileExtension();
  1634. fileList.Append( fileName );
  1635. }
  1636. bool bCon = cvarSystem->GetCVarBool( "con_noPrint" );
  1637. cvarSystem->SetCVarBool( "con_noPrint", true );
  1638. for ( i = 0; i < fileList.Num(); i++ ) {
  1639. workName = fileList[i];
  1640. workName += "/";
  1641. workName += p;
  1642. int workNote = noteNumber;
  1643. R_ScreenshotFilename( workNote, workName, shotName );
  1644. noteNum = shotName;
  1645. noteNum.StripPath();
  1646. noteNum.StripFileExtension();
  1647. if ( severity && *severity ) {
  1648. workName = severity;
  1649. workName += "viewNotes";
  1650. }
  1651. sprintf( str, "recordViewNotes \"%s\" \"%s\" \"%s\"\n", workName.c_str(), noteNum.c_str(), guiTakeNotes->State().GetString( "note" ) );
  1652. cmdSystem->BufferCommandText( CMD_EXEC_NOW, str );
  1653. cmdSystem->ExecuteCommandBuffer();
  1654. UpdateScreen();
  1655. renderSystem->TakeScreenshot( renderSystem->GetScreenWidth(), renderSystem->GetScreenHeight(), shotName, 1, NULL );
  1656. }
  1657. noteNumber++;
  1658. for ( int tries = 0; tries < 10; tries++ ) {
  1659. file = fileSystem->OpenExplicitFileWrite( "p:/viewnotes/notenumber.dat" );
  1660. if ( file != NULL ) {
  1661. break;
  1662. }
  1663. Sys_Sleep( 500 );
  1664. }
  1665. if ( file ) {
  1666. file->Write( &noteNumber, 4 );
  1667. fileSystem->CloseFile( file );
  1668. }
  1669. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "closeViewNotes\n" );
  1670. cvarSystem->SetCVarBool( "con_noPrint", bCon );
  1671. }
  1672. }
  1673. /*
  1674. ===============
  1675. idSessionLocal::SetCDKeyGuiVars
  1676. ===============
  1677. */
  1678. void idSessionLocal::SetCDKeyGuiVars( void ) {
  1679. //common->Printf("banana bread\n");
  1680. //bc
  1681. /*
  1682. if ( !guiMainMenu ) {
  1683. return;
  1684. }
  1685. guiMainMenu->SetStateString( "str_d3key_state", common->GetLanguageDict()->GetString( va( "#str_071%d", 86 + cdkey_state ) ) );
  1686. guiMainMenu->SetStateString( "str_xpkey_state", common->GetLanguageDict()->GetString( va( "#str_071%d", 86 + xpkey_state ) ) );
  1687. */
  1688. }