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