WOLWelcomeMenu.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. ///////////////////////////////////////////////////////////////////////////////////////
  24. // FILE: WOLWelcomeMenu.cpp
  25. // Author: Chris Huybregts, November 2001
  26. // Description: Lan Lobby Menu
  27. ///////////////////////////////////////////////////////////////////////////////////////
  28. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  29. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  30. #include "GameSpy/peer/peer.h"
  31. #include "Common/GameEngine.h"
  32. #include "Common/GameSpyMiscPreferences.h"
  33. #include "Common/CustomMatchPreferences.h"
  34. #include "Common/GlobalData.h"
  35. #include "Common/UserPreferences.h"
  36. #include "GameClient/AnimateWindowManager.h"
  37. #include "GameClient/Display.h"
  38. #include "GameClient/WindowLayout.h"
  39. #include "GameClient/Gadget.h"
  40. #include "GameClient/GameText.h"
  41. #include "GameClient/Shell.h"
  42. #include "GameClient/KeyDefs.h"
  43. #include "GameClient/GameWindowManager.h"
  44. #include "GameClient/GadgetListBox.h"
  45. #include "GameClient/GadgetTextEntry.h"
  46. #include "GameClient/GadgetStaticText.h"
  47. #include "GameClient/MessageBox.h"
  48. #include "GameClient/GameWindowTransitions.h"
  49. #include "GameNetwork/FirewallHelper.h"
  50. #include "GameNetwork/GameSpyOverlay.h"
  51. #include "GameNetwork/GameSpy/BuddyDefs.h"
  52. #include "GameNetwork/GameSpy/BuddyThread.h"
  53. #include "GameNetwork/GameSpy/PeerDefs.h"
  54. #include "GameNetwork/GameSpy/PeerThread.h"
  55. #include "GameNetwork/GameSpy/PersistentStorageDefs.h"
  56. #include "GameNetwork/GameSpy/PersistentStorageThread.h"
  57. #include "GameNetwork/GameSpy/BuddyThread.h"
  58. #include "GameNetwork/GameSpy/ThreadUtils.h"
  59. #include "GameNetwork/GameSpy/MainMenuUtils.h"
  60. #include "GameNetwork/WOLBrowser/WebBrowser.h"
  61. #ifdef _INTERNAL
  62. // for occasional debugging...
  63. //#pragma optimize("", off)
  64. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  65. #endif
  66. // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
  67. static Bool isShuttingDown = FALSE;
  68. static Bool buttonPushed = FALSE;
  69. static char *nextScreen = NULL;
  70. // window ids ------------------------------------------------------------------------------
  71. static NameKeyType parentWOLWelcomeID = NAMEKEY_INVALID;
  72. static NameKeyType buttonBackID = NAMEKEY_INVALID;
  73. static NameKeyType buttonQuickMatchID = NAMEKEY_INVALID;
  74. static NameKeyType buttonLobbyID = NAMEKEY_INVALID;
  75. static NameKeyType buttonBuddiesID = NAMEKEY_INVALID;
  76. static NameKeyType buttonLadderID = NAMEKEY_INVALID;
  77. static NameKeyType buttonMyInfoID = NAMEKEY_INVALID;
  78. static NameKeyType listboxInfoID = NAMEKEY_INVALID;
  79. static NameKeyType buttonOptionsID = NAMEKEY_INVALID;
  80. // Window Pointers ------------------------------------------------------------------------
  81. static GameWindow *parentWOLWelcome = NULL;
  82. static GameWindow *buttonBack = NULL;
  83. static GameWindow *buttonQuickMatch = NULL;
  84. static GameWindow *buttonLobby = NULL;
  85. static GameWindow *buttonBuddies = NULL;
  86. static GameWindow *buttonLadder = NULL;
  87. static GameWindow *buttonMyInfo = NULL;
  88. static GameWindow *buttonbuttonOptions = NULL;
  89. static WindowLayout *welcomeLayout = NULL;
  90. static GameWindow *listboxInfo = NULL;
  91. static GameWindow *staticTextServerName = NULL;
  92. static GameWindow *staticTextLastUpdated = NULL;
  93. static GameWindow *staticTextLadderWins = NULL;
  94. static GameWindow *staticTextLadderLosses = NULL;
  95. static GameWindow *staticTextLadderRank = NULL;
  96. static GameWindow *staticTextLadderPoints = NULL;
  97. static GameWindow *staticTextLadderDisconnects = NULL;
  98. static GameWindow *staticTextHighscoreWins = NULL;
  99. static GameWindow *staticTextHighscoreLosses = NULL;
  100. static GameWindow *staticTextHighscoreRank = NULL;
  101. static GameWindow *staticTextHighscorePoints = NULL;
  102. static UnicodeString gServerName;
  103. void updateServerDisplay(UnicodeString serverName)
  104. {
  105. if (staticTextServerName)
  106. {
  107. GadgetStaticTextSetText(staticTextServerName, serverName);
  108. }
  109. gServerName = serverName;
  110. }
  111. /*
  112. void updateLocalPlayerScores(AsciiString name, const WOL::Ladder *ladder, const WOL::Highscore *highscore)
  113. {
  114. if (ladder)
  115. {
  116. AsciiString a;
  117. UnicodeString u;
  118. a.format("%d", ladder->wins);
  119. u.translate(a);
  120. GadgetStaticTextSetText(staticTextLadderWins, u);
  121. a.format("%d", ladder->losses);
  122. u.translate(a);
  123. GadgetStaticTextSetText(staticTextLadderLosses, u);
  124. a.format("%d", ladder->rank);
  125. u.translate(a);
  126. GadgetStaticTextSetText(staticTextLadderRank, u);
  127. a.format("%d", ladder->points);
  128. u.translate(a);
  129. GadgetStaticTextSetText(staticTextLadderPoints, u);
  130. a.format("%d", ladder->disconnects);
  131. u.translate(a);
  132. GadgetStaticTextSetText(staticTextLadderDisconnects, u);
  133. }
  134. if (highscore)
  135. {
  136. AsciiString a;
  137. UnicodeString u;
  138. a.format("%d", highscore->wins);
  139. u.translate(a);
  140. GadgetStaticTextSetText(staticTextHighscoreWins, u);
  141. a.format("%d", highscore->losses);
  142. u.translate(a);
  143. GadgetStaticTextSetText(staticTextHighscoreLosses, u);
  144. a.format("%d", highscore->rank);
  145. u.translate(a);
  146. GadgetStaticTextSetText(staticTextHighscoreRank, u);
  147. a.format("%d", highscore->points);
  148. u.translate(a);
  149. GadgetStaticTextSetText(staticTextHighscorePoints, u);
  150. }
  151. }
  152. */
  153. static void enableControls( Bool state )
  154. {
  155. #ifndef _PLAYTEST
  156. if (buttonQuickMatch)
  157. buttonQuickMatch->winEnable(state);
  158. #else
  159. if (buttonQuickMatch)
  160. buttonQuickMatch->winEnable(FALSE);
  161. #endif
  162. if (buttonLobby)
  163. buttonLobby->winEnable(state);
  164. }
  165. //-------------------------------------------------------------------------------------------------
  166. /** This is called when a shutdown is complete for this menu */
  167. //-------------------------------------------------------------------------------------------------
  168. static void shutdownComplete( WindowLayout *layout )
  169. {
  170. isShuttingDown = FALSE;
  171. // hide the layout
  172. layout->hide( TRUE );
  173. // our shutdown is complete
  174. TheShell->shutdownComplete( layout, (nextScreen != NULL) );
  175. if (nextScreen != NULL)
  176. {
  177. TheShell->push(nextScreen);
  178. }
  179. nextScreen = NULL;
  180. } // end if
  181. //-------------------------------------------------------------------------------------------------
  182. /** Handle Num Players Online data */
  183. //-------------------------------------------------------------------------------------------------
  184. static Int lastNumPlayersOnline = 0;
  185. static UnsignedByte grabUByte(const char *s)
  186. {
  187. char tmp[5] = "0xff";
  188. tmp[2] = s[0];
  189. tmp[3] = s[1];
  190. UnsignedByte b = strtol(tmp, NULL, 16);
  191. return b;
  192. }
  193. static void updateNumPlayersOnline(void)
  194. {
  195. GameWindow *playersOnlineWindow = TheWindowManager->winGetWindowFromId(
  196. NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextNumPlayersOnline") );
  197. if (playersOnlineWindow)
  198. {
  199. UnicodeString valStr;
  200. valStr.format(TheGameText->fetch("GUI:NumPlayersOnline"), lastNumPlayersOnline);
  201. GadgetStaticTextSetText(playersOnlineWindow, valStr);
  202. }
  203. if (listboxInfo && TheGameSpyInfo)
  204. {
  205. GadgetListBoxReset(listboxInfo);
  206. AsciiString aLine;
  207. UnicodeString line;
  208. AsciiString aMotd = TheGameSpyInfo->getMOTD();
  209. UnicodeString headingStr;
  210. headingStr.format(TheGameText->fetch("MOTD:NumPlayersHeading"), lastNumPlayersOnline);
  211. while (headingStr.nextToken(&line, UnicodeString(L"\n")))
  212. {
  213. if (line.getCharAt(line.getLength()-1) == '\r')
  214. line.removeLastChar(); // there is a trailing '\r'
  215. line.trim();
  216. if (line.isEmpty())
  217. {
  218. line = UnicodeString(L" ");
  219. }
  220. GadgetListBoxAddEntryText(listboxInfo, line, GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1);
  221. }
  222. GadgetListBoxAddEntryText(listboxInfo, UnicodeString(L" "), GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1);
  223. while (aMotd.nextToken(&aLine, "\n"))
  224. {
  225. if (aLine.getCharAt(aLine.getLength()-1) == '\r')
  226. aLine.removeLastChar(); // there is a trailing '\r'
  227. aLine.trim();
  228. if (aLine.isEmpty())
  229. {
  230. aLine = " ";
  231. }
  232. Color c = GameSpyColor[GSCOLOR_MOTD];
  233. if (aLine.startsWith("\\\\"))
  234. {
  235. aLine = aLine.str()+1;
  236. }
  237. else if (aLine.startsWith("\\") && aLine.getLength() > 9)
  238. {
  239. // take out the hex value from strings starting as "\ffffffffText"
  240. UnsignedByte a, r, g, b;
  241. a = grabUByte(aLine.str()+1);
  242. r = grabUByte(aLine.str()+3);
  243. g = grabUByte(aLine.str()+5);
  244. b = grabUByte(aLine.str()+7);
  245. c = GameMakeColor(r, g, b, a);
  246. DEBUG_LOG(("MOTD line '%s' has color %X\n", aLine.str(), c));
  247. aLine = aLine.str() + 9;
  248. }
  249. line = UnicodeString(MultiByteToWideCharSingleLine(aLine.str()).c_str());
  250. GadgetListBoxAddEntryText(listboxInfo, line, c, -1, -1);
  251. }
  252. }
  253. }
  254. void HandleNumPlayersOnline( Int numPlayersOnline )
  255. {
  256. lastNumPlayersOnline = numPlayersOnline;
  257. if (lastNumPlayersOnline < 1)
  258. lastNumPlayersOnline = 1;
  259. updateNumPlayersOnline();
  260. }
  261. //-------------------------------------------------------------------------------------------------
  262. /** Handle Overall Stats data */
  263. //-------------------------------------------------------------------------------------------------
  264. static OverallStats s_statsUSA, s_statsChina, s_statsGLA;
  265. OverallStats::OverallStats()
  266. {
  267. for (Int i=0; i<STATS_MAX; ++i)
  268. {
  269. wins[i] = losses[i] = 0;
  270. }
  271. }
  272. static UnicodeString calcPercent(const OverallStats& stats, Int n, UnicodeString sideStr)
  273. {
  274. // per side percentage of total wins
  275. Real winPercentUSA = s_statsUSA.wins[n]*100/INT_TO_REAL(max(1, s_statsUSA.wins[n]+s_statsUSA.losses[n])); // 0.0f - 100.0f
  276. Real winPercentChina = s_statsChina.wins[n]*100/INT_TO_REAL(max(1, s_statsChina.wins[n]+s_statsChina.losses[n])); // 0.0f - 100.0f
  277. Real winPercentGLA = s_statsGLA.wins[n]*100/INT_TO_REAL(max(1, s_statsGLA.wins[n]+s_statsGLA.losses[n])); // 0.0f - 100.0f
  278. Real thisWinPercent = stats.wins[n]*100/INT_TO_REAL(max(1, stats.wins[n]+stats.losses[n])); // 0.0f - 100.0f
  279. Real totalWinPercent = winPercentUSA + winPercentChina + winPercentGLA;
  280. Real val = thisWinPercent*100/max(1.0f,totalWinPercent);
  281. UnicodeString s;
  282. s.format(TheGameText->fetch("GUI:PerSideWinPercentage"), REAL_TO_INT(val), sideStr.str());
  283. /*
  284. Int totalDenominator = s_statsUSA.wins[n] + s_statsChina.wins[n] + s_statsGLA.wins[n];
  285. if (!totalDenominator)
  286. totalDenominator = 1;
  287. UnicodeString s;
  288. s.format(TheGameText->fetch("GUI:PerSideWinPercentage"), REAL_TO_INT(stats.wins[n]*100/totalDenominator), sideStr.str());
  289. */
  290. return s;
  291. }
  292. static void updateOverallStats(void)
  293. {
  294. UnicodeString usa, china, gla;
  295. GameWindow *win;
  296. usa = calcPercent(s_statsUSA, STATS_LASTWEEK, TheGameText->fetch("SIDE:America"));
  297. china = calcPercent(s_statsChina, STATS_LASTWEEK, TheGameText->fetch("SIDE:China"));
  298. gla = calcPercent(s_statsGLA, STATS_LASTWEEK, TheGameText->fetch("SIDE:GLA"));
  299. DEBUG_LOG(("Last Week: %ls %ls %ls\n", usa.str(), china.str(), gla.str()));
  300. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSALastWeek") );
  301. GadgetStaticTextSetText(win, usa);
  302. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaLastWeek") );
  303. GadgetStaticTextSetText(win, china);
  304. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLALastWeek") );
  305. GadgetStaticTextSetText(win, gla);
  306. usa = calcPercent(s_statsUSA, STATS_TODAY, TheGameText->fetch("SIDE:America"));
  307. china = calcPercent(s_statsChina, STATS_TODAY, TheGameText->fetch("SIDE:China"));
  308. gla = calcPercent(s_statsGLA, STATS_TODAY, TheGameText->fetch("SIDE:GLA"));
  309. DEBUG_LOG(("Today: %ls %ls %ls\n", usa.str(), china.str(), gla.str()));
  310. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSAToday") );
  311. GadgetStaticTextSetText(win, usa);
  312. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaToday") );
  313. GadgetStaticTextSetText(win, china);
  314. win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLAToday") );
  315. GadgetStaticTextSetText(win, gla);
  316. }
  317. void HandleOverallStats( const OverallStats& USA, const OverallStats& China, const OverallStats& GLA )
  318. {
  319. s_statsUSA = USA;
  320. s_statsChina = China;
  321. s_statsGLA = GLA;
  322. updateOverallStats();
  323. }
  324. //-------------------------------------------------------------------------------------------------
  325. /** Handle player stats */
  326. //-------------------------------------------------------------------------------------------------
  327. void UpdateLocalPlayerStats(void)
  328. {
  329. GameWindow *welcomeParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:WOLWelcomeMenuParent") );
  330. if (welcomeParent)
  331. {
  332. PopulatePlayerInfoWindows( "WOLWelcomeMenu.wnd" );
  333. }
  334. else
  335. {
  336. PopulatePlayerInfoWindows( "WOLQuickMatchMenu.wnd" );
  337. }
  338. return;
  339. }
  340. static Bool raiseMessageBoxes = FALSE;
  341. //-------------------------------------------------------------------------------------------------
  342. /** Initialize the WOL Welcome Menu */
  343. //-------------------------------------------------------------------------------------------------
  344. void WOLWelcomeMenuInit( WindowLayout *layout, void *userData )
  345. {
  346. nextScreen = NULL;
  347. buttonPushed = FALSE;
  348. isShuttingDown = FALSE;
  349. welcomeLayout = layout;
  350. //TheWOL->reset();
  351. parentWOLWelcomeID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:WOLWelcomeMenuParent" ) );
  352. buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBack" ) );
  353. parentWOLWelcome = TheWindowManager->winGetWindowFromId( NULL, parentWOLWelcomeID );
  354. buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID);
  355. buttonOptionsID = TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:ButtonOptions" );
  356. buttonbuttonOptions = TheWindowManager->winGetWindowFromId( NULL, buttonOptionsID);
  357. listboxInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:InfoListbox" ) );
  358. listboxInfo = TheWindowManager->winGetWindowFromId( NULL, listboxInfoID);
  359. staticTextServerName = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  360. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextServerName" ));
  361. staticTextLastUpdated = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  362. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLastUpdated" ));
  363. staticTextLadderWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  364. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderWins" ));
  365. staticTextLadderLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  366. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderLosses" ));
  367. staticTextLadderPoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  368. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderPoints" ));
  369. staticTextLadderRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  370. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderRank" ));
  371. staticTextLadderDisconnects = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  372. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextDisconnects" ));
  373. staticTextHighscoreWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  374. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreWins" ));
  375. staticTextHighscoreLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  376. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreLosses" ));
  377. staticTextHighscorePoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  378. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscorePoints" ));
  379. staticTextHighscoreRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
  380. TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreRank" ));
  381. if (staticTextServerName)
  382. {
  383. GadgetStaticTextSetText(staticTextServerName, gServerName);
  384. }
  385. GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId(parentWOLWelcome, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextTitle"));
  386. if (staticTextTitle && TheGameSpyInfo)
  387. {
  388. UnicodeString title;
  389. title.format(TheGameText->fetch("GUI:WOLWelcome"), TheGameSpyInfo->getLocalBaseName().str());
  390. GadgetStaticTextSetText(staticTextTitle, title);
  391. }
  392. // Clear some defaults
  393. /*
  394. UnicodeString questionMark = UnicodeString(L"?");
  395. GadgetStaticTextSetText(staticTextLastUpdated, questionMark);
  396. GadgetStaticTextSetText(staticTextLadderWins, questionMark);
  397. GadgetStaticTextSetText(staticTextLadderLosses, questionMark);
  398. GadgetStaticTextSetText(staticTextLadderPoints, questionMark);
  399. GadgetStaticTextSetText(staticTextLadderRank, questionMark);
  400. GadgetStaticTextSetText(staticTextLadderDisconnects, questionMark);
  401. GadgetStaticTextSetText(staticTextHighscoreWins, questionMark);
  402. GadgetStaticTextSetText(staticTextHighscoreLosses, questionMark);
  403. GadgetStaticTextSetText(staticTextHighscorePoints, questionMark);
  404. GadgetStaticTextSetText(staticTextHighscoreRank, questionMark);
  405. */
  406. //DEBUG_ASSERTCRASH(listboxInfo, ("No control found!"));
  407. buttonQuickMatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonQuickMatch" ) );
  408. buttonQuickMatch = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonQuickMatchID );
  409. buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonCustomMatch" ) );
  410. buttonLobby = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLobbyID );
  411. buttonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBuddies" ) );
  412. buttonBuddies = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonBuddiesID );
  413. buttonMyInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonMyInfo" ) );
  414. buttonMyInfo = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonMyInfoID );
  415. buttonLadderID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonLadder" ) );
  416. buttonLadder = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLadderID );
  417. if (TheFirewallHelper == NULL) {
  418. TheFirewallHelper = createFirewallHelper();
  419. }
  420. if (TheFirewallHelper->detectFirewall() == TRUE) {
  421. // don't need to detect firewall, already been done.
  422. delete TheFirewallHelper;
  423. TheFirewallHelper = NULL;
  424. }
  425. /*
  426. if (TheGameSpyChat && TheGameSpyChat->isConnected())
  427. {
  428. const char *keys[3] = { "locale", "wins", "losses" };
  429. char valueStrings[3][20];
  430. char *values[3] = { valueStrings[0], valueStrings[1], valueStrings[2] };
  431. _snprintf(values[0], 20, "%s", TheGameSpyPlayerInfo->getLocale().str());
  432. _snprintf(values[1], 20, "%d", TheGameSpyPlayerInfo->getWins());
  433. _snprintf(values[2], 20, "%d", TheGameSpyPlayerInfo->getLosses());
  434. peerSetGlobalKeys(TheGameSpyChat->getPeer(), 3, (const char **)keys, (const char **)values);
  435. peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), GroupRoom, 3, keys, PEERFalse);
  436. peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), StagingRoom, 3, keys, PEERFalse);
  437. }
  438. */
  439. // // animate controls
  440. // TheShell->registerWithAnimateManager(buttonQuickMatch, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800);
  441. // TheShell->registerWithAnimateManager(buttonLobby, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600);
  442. // //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400);
  443. // TheShell->registerWithAnimateManager(buttonBuddies, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200);
  444. // //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 1);
  445. // TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 1);
  446. // Show Menu
  447. layout->hide( FALSE );
  448. // Set Keyboard to Main Parent
  449. TheWindowManager->winSetFocus( parentWOLWelcome );
  450. enableControls( TheGameSpyInfo->gotGroupRoomList() );
  451. TheShell->showShellMap(TRUE);
  452. updateNumPlayersOnline();
  453. updateOverallStats();
  454. UpdateLocalPlayerStats();
  455. GameSpyMiscPreferences cPref;
  456. if (cPref.getLocale() < LOC_MIN || cPref.getLocale() > LOC_MAX)
  457. {
  458. GameSpyOpenOverlay(GSOVERLAY_LOCALESELECT);
  459. }
  460. raiseMessageBoxes = TRUE;
  461. TheTransitionHandler->setGroup("WOLWelcomeMenuFade");
  462. } // WOLWelcomeMenuInit
  463. //-------------------------------------------------------------------------------------------------
  464. /** WOL Welcome Menu shutdown method */
  465. //-------------------------------------------------------------------------------------------------
  466. void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData )
  467. {
  468. listboxInfo = NULL;
  469. if (TheFirewallHelper != NULL) {
  470. delete TheFirewallHelper;
  471. TheFirewallHelper = NULL;
  472. }
  473. isShuttingDown = TRUE;
  474. // if we are shutting down for an immediate pop, skip the animations
  475. Bool popImmediate = *(Bool *)userData;
  476. if( popImmediate )
  477. {
  478. shutdownComplete( layout );
  479. return;
  480. } //end if
  481. TheShell->reverseAnimatewindow();
  482. TheTransitionHandler->reverse("WOLWelcomeMenuFade");
  483. RaiseGSMessageBox();
  484. } // WOLWelcomeMenuShutdown
  485. //-------------------------------------------------------------------------------------------------
  486. /** WOL Welcome Menu update method */
  487. //-------------------------------------------------------------------------------------------------
  488. void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData)
  489. {
  490. // We'll only be successful if we've requested to
  491. if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished())
  492. shutdownComplete(layout);
  493. if (raiseMessageBoxes)
  494. {
  495. RaiseGSMessageBox();
  496. raiseMessageBoxes = FALSE;
  497. }
  498. if (TheFirewallHelper != NULL)
  499. {
  500. if (TheFirewallHelper->behaviorDetectionUpdate())
  501. {
  502. TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior();
  503. TheFirewallHelper->writeFirewallBehavior();
  504. TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore.
  505. // we are now done with the firewall helper
  506. delete TheFirewallHelper;
  507. TheFirewallHelper = NULL;
  508. }
  509. }
  510. if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue)
  511. {
  512. HandleBuddyResponses();
  513. HandlePersistentStorageResponses();
  514. Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate();
  515. Bool sawImportantMessage = FALSE;
  516. PeerResponse resp;
  517. while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp ))
  518. {
  519. switch (resp.peerResponseType)
  520. {
  521. case PeerResponse::PEERRESPONSE_GROUPROOM:
  522. {
  523. GameSpyGroupRoom room;
  524. room.m_groupID = resp.groupRoom.id;
  525. room.m_maxWaiting = resp.groupRoom.maxWaiting;
  526. room.m_name = resp.groupRoomName.c_str();
  527. room.m_translatedName = UnicodeString(L"TEST");
  528. room.m_numGames = resp.groupRoom.numGames;
  529. room.m_numPlaying = resp.groupRoom.numPlaying;
  530. room.m_numWaiting = resp.groupRoom.numWaiting;
  531. TheGameSpyInfo->addGroupRoom( room );
  532. if (room.m_groupID == 0)
  533. {
  534. enableControls( TRUE );
  535. }
  536. }
  537. break;
  538. case PeerResponse::PEERRESPONSE_JOINGROUPROOM:
  539. {
  540. sawImportantMessage = TRUE;
  541. enableControls( TRUE );
  542. if (resp.joinGroupRoom.ok)
  543. {
  544. //buttonPushed = TRUE;
  545. TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id);
  546. //GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinOK") );
  547. buttonPushed = TRUE;
  548. nextScreen = "Menus/WOLCustomLobby.wnd";
  549. TheShell->pop();
  550. //TheShell->push( "Menus/WOLCustomLobby.wnd" );
  551. }
  552. else
  553. {
  554. GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinFail") );
  555. }
  556. }
  557. break;
  558. case PeerResponse::PEERRESPONSE_DISCONNECT:
  559. {
  560. sawImportantMessage = TRUE;
  561. UnicodeString title, body;
  562. AsciiString disconMunkee;
  563. disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason);
  564. title = TheGameText->fetch( "GUI:GSErrorTitle" );
  565. body = TheGameText->fetch( disconMunkee );
  566. GameSpyCloseAllOverlays();
  567. GSMessageBoxOk( title, body );
  568. TheShell->pop();
  569. }
  570. break;
  571. }
  572. }
  573. }
  574. }// WOLWelcomeMenuUpdate
  575. //-------------------------------------------------------------------------------------------------
  576. /** WOL Welcome Menu input callback */
  577. //-------------------------------------------------------------------------------------------------
  578. WindowMsgHandledType WOLWelcomeMenuInput( GameWindow *window, UnsignedInt msg,
  579. WindowMsgData mData1, WindowMsgData mData2 )
  580. {
  581. switch( msg )
  582. {
  583. // --------------------------------------------------------------------------------------------
  584. case GWM_CHAR:
  585. {
  586. UnsignedByte key = mData1;
  587. UnsignedByte state = mData2;
  588. if (buttonPushed)
  589. break;
  590. switch( key )
  591. {
  592. // ----------------------------------------------------------------------------------------
  593. case KEY_ESC:
  594. {
  595. //
  596. // send a simulated selected event to the parent window of the
  597. // back/exit button
  598. //
  599. if( BitTest( state, KEY_STATE_UP ) )
  600. {
  601. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  602. (WindowMsgData)buttonBack, buttonBackID );
  603. } // end if
  604. // don't let key fall through anywhere else
  605. return MSG_HANDLED;
  606. } // end escape
  607. } // end switch( key )
  608. } // end char
  609. } // end switch( msg )
  610. return MSG_IGNORED;
  611. }// WOLWelcomeMenuInput
  612. //-------------------------------------------------------------------------------------------------
  613. /** WOL Welcome Menu window system callback */
  614. //-------------------------------------------------------------------------------------------------
  615. WindowMsgHandledType WOLWelcomeMenuSystem( GameWindow *window, UnsignedInt msg,
  616. WindowMsgData mData1, WindowMsgData mData2 )
  617. {
  618. UnicodeString txtInput;
  619. switch( msg )
  620. {
  621. case GWM_CREATE:
  622. {
  623. break;
  624. } // case GWM_DESTROY:
  625. case GWM_DESTROY:
  626. {
  627. break;
  628. } // case GWM_DESTROY:
  629. case GWM_INPUT_FOCUS:
  630. {
  631. // if we're givin the opportunity to take the keyboard focus we must say we want it
  632. if( mData1 == TRUE )
  633. *(Bool *)mData2 = TRUE;
  634. return MSG_HANDLED;
  635. }//case GWM_INPUT_FOCUS:
  636. case GBM_SELECTED:
  637. {
  638. if (buttonPushed)
  639. break;
  640. GameWindow *control = (GameWindow *)mData1;
  641. Int controlID = control->winGetWindowId();
  642. if ( controlID == buttonBackID )
  643. {
  644. //DEBUG_ASSERTCRASH(TheGameSpyChat->getPeer(), ("No GameSpy Peer object!"));
  645. //TheGameSpyChat->disconnectFromChat();
  646. PeerRequest req;
  647. req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT;
  648. TheGameSpyPeerMessageQueue->addRequest( req );
  649. BuddyRequest breq;
  650. breq.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGOUT;
  651. TheGameSpyBuddyMessageQueue->addRequest( breq );
  652. DEBUG_LOG(("Tearing down GameSpy from WOLWelcomeMenuSystem(GBM_SELECTED)\n"));
  653. TearDownGameSpy();
  654. /*
  655. if (TheGameSpyChat->getPeer())
  656. {
  657. peerDisconnect(TheGameSpyChat->getPeer());
  658. }
  659. */
  660. buttonPushed = TRUE;
  661. TheShell->pop();
  662. /// @todo: log out instead of disconnecting
  663. //TheWOL->addCommand( WOL::WOLCOMMAND_LOGOUT );
  664. /**
  665. closeAllOverlays();
  666. TheShell->pop();
  667. delete TheWOL;
  668. TheWOL = NULL;
  669. delete TheWOLGame;
  670. TheWOLGame = NULL;
  671. **/
  672. } //if ( controlID == buttonBack )
  673. else if (controlID == buttonOptionsID)
  674. {
  675. GameSpyOpenOverlay( GSOVERLAY_OPTIONS );
  676. }
  677. else if (controlID == buttonQuickMatchID)
  678. {
  679. GameSpyMiscPreferences mPref;
  680. if ((TheDisplay->getWidth() != 800 || TheDisplay->getHeight() != 600) && mPref.getQuickMatchResLocked())
  681. {
  682. GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:QuickMatch800x600"));
  683. }
  684. else
  685. {
  686. buttonPushed = TRUE;
  687. nextScreen = "Menus/WOLQuickMatchMenu.wnd";
  688. TheShell->pop();
  689. }
  690. }// else if
  691. else if (controlID == buttonMyInfoID )
  692. {
  693. SetLookAtPlayer(TheGameSpyInfo->getLocalProfileID(), TheGameSpyInfo->getLocalName());
  694. GameSpyToggleOverlay(GSOVERLAY_PLAYERINFO);
  695. }
  696. else if (controlID == buttonLobbyID)
  697. {
  698. //TheGameSpyChat->clearGroupRoomList();
  699. //peerListGroupRooms(TheGameSpyChat->getPeer(), ListGroupRoomsCallback, NULL, PEERTrue);
  700. TheGameSpyInfo->joinBestGroupRoom();
  701. enableControls( FALSE );
  702. /*
  703. TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY);
  704. TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM);
  705. TheWOL->setState( WOL::WOLAPI_LOBBY );
  706. TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS );
  707. */
  708. }// else if
  709. else if (controlID == buttonBuddiesID)
  710. {
  711. GameSpyToggleOverlay( GSOVERLAY_BUDDY );
  712. /*
  713. Bool joinedRoom = FALSE;
  714. ClearGroupRoomList();
  715. peerJoinTitleRoom(TheGameSpyChat->getPeer(), JoinRoomCallback, &joinedRoom, PEERTrue);
  716. if (joinedRoom)
  717. {
  718. GameSpyUsingGroupRooms = FALSE;
  719. GameSpyCurrentGroupRoomID = 0;
  720. TheShell->pop();
  721. TheShell->push("Menus/WOLCustomLobby.wnd");
  722. }
  723. else
  724. {
  725. GameSpyCurrentGroupRoomID = 0;
  726. GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join title room"), NULL);
  727. }
  728. */
  729. }
  730. else if (controlID == buttonLadderID)
  731. {
  732. TheShell->push(AsciiString("Menus/WOLLadderScreen.wnd"));
  733. }
  734. break;
  735. }// case GBM_SELECTED:
  736. case GEM_EDIT_DONE:
  737. {
  738. break;
  739. }
  740. default:
  741. return MSG_IGNORED;
  742. }//Switch
  743. return MSG_HANDLED;
  744. }// WOLWelcomeMenuSystem