WOL_CHAT.CPP 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. #ifdef WOLAPI_INTEGRATION
  15. // wol_chat.cpp
  16. // ajw 7/8/98
  17. #include "function.h"
  18. #include "iconlist.h"
  19. #include "WolapiOb.h"
  20. #include "SEditDlg.h"
  21. #include "WolStrng.h"
  22. #include "ToolTip.h"
  23. //#include "WolDebug.h"
  24. void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );
  25. void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap );
  26. bool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, Channel* pChannel, char* szChannelName, bool bGame );
  27. bool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex, bool bGame );
  28. bool ExitChatChannel( WolapiObject* pWO );
  29. void CreateChatChannel( WolapiObject* pWO );
  30. bool CreateGameChannel( WolapiObject* pWO, const CREATEGAMEINFO& cgi );
  31. bool ProcessChannelListSelection( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex );
  32. enum LIST_EXPAND_STATE
  33. {
  34. LES_NORMAL,
  35. LES_CHANNELS_EXPANDED,
  36. LES_USERS_EXPANDED,
  37. };
  38. static LIST_EXPAND_STATE lesCurrent = LES_NORMAL;
  39. bool OnExpandChannelList( IconListClass& chanlist, IconListClass& userlist );
  40. bool OnExpandUserList( IconListClass& chanlist, IconListClass& userlist );
  41. void ResizeChannelList( IconListClass& chanlist, bool bExpand );
  42. void ResizeUserList( IconListClass& userlist, bool bExpand );
  43. bool bLinkInList( const LinkClass* pListHead, const LinkClass* pLinkToFind );
  44. extern CREATEGAMEINFO WOL_CreateGame_Dialog( WolapiObject* pWO );
  45. static int d_chanlist_w;
  46. static int d_chanlist_h;
  47. static int d_chanlist_x;
  48. static int d_chanlist_y;
  49. static int d_userlist_w;
  50. static int d_userlist_h;
  51. static int d_userlist_x;
  52. static int d_userlist_y;
  53. #define DRAWTOGDOWN Turn_Off()
  54. #define DRAWTOGUP Turn_On()
  55. //***********************************************************************************************
  56. int WOL_Chat_Dialog( WolapiObject* pWO )
  57. {
  58. int rc;
  59. bool bFirsttime = true;
  60. bool bHackFocus = true;
  61. //------------------------------------------------------------------------
  62. // Dialog & button dimensions
  63. //------------------------------------------------------------------------
  64. int d_dialog_w = 320 *RESFACTOR; // dialog width
  65. int d_dialog_h = 200 *RESFACTOR; // dialog height
  66. int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2); // dialog x-coord
  67. int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2); // centered y-coord
  68. int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
  69. int d_text_h = 12;
  70. int d_margin1 = 34; // large margin
  71. int d_margin2 = 14; // small margin
  72. int d_chatlist_w = 340;
  73. int d_chatlist_x = d_dialog_x + d_margin1;
  74. int d_chatlist_y = d_dialog_y + d_margin2 + d_margin1 + 27;
  75. int d_chatlist_h = 337 - d_chatlist_y;
  76. d_chanlist_w = 227;
  77. d_chanlist_h = 50 * RESFACTOR;
  78. d_chanlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_chanlist_w);
  79. d_chanlist_y = d_chatlist_y;
  80. d_userlist_w = d_chanlist_w;
  81. // int d_userlist_h = ((10 * 6) + 3) *RESFACTOR;
  82. d_userlist_x = d_chanlist_x;
  83. d_userlist_y = d_chanlist_y + d_chanlist_h + 14 + 5;
  84. d_userlist_h = d_chatlist_y + d_chatlist_h - d_userlist_y;
  85. int d_action_w = 100;
  86. int d_action_h = 9 *RESFACTOR;
  87. int d_action_x = d_dialog_x + 500;
  88. int d_action_y = 365;
  89. // int d_chanpriv_w = 60;
  90. // int d_chanpriv_h = 9 *RESFACTOR;
  91. // int d_chanpriv_x = d_dialog_x + 150;
  92. // int d_chanpriv_y = d_action_y;
  93. // int d_cgame_w = 60;
  94. // int d_cgame_h = 9 *RESFACTOR;
  95. // int d_cgame_x = d_dialog_x + 390; //d_dialog_cx - d_cgame_w / 2;
  96. // int d_cgame_y = d_action_y;
  97. int d_back_w = 100;
  98. int d_back_h = 9 *RESFACTOR;
  99. int d_back_x = d_dialog_x + 100;
  100. int d_back_y = d_action_y;
  101. int d_join_w = 100;
  102. int d_join_h = 9 *RESFACTOR;
  103. int d_join_x = d_dialog_x + 210;
  104. int d_join_y = d_action_y;
  105. int d_create_w = 100;
  106. int d_create_h = 9 *RESFACTOR;
  107. int d_create_x = d_dialog_x + 320; //((d_dialog_w * 5) / 6) - (d_create_w / 2);
  108. int d_create_y = d_action_y;
  109. int d_send_w = d_chanlist_x + d_chanlist_w - d_chatlist_x;
  110. int d_send_h = 9 *RESFACTOR;
  111. int d_send_x = d_chatlist_x;
  112. int d_send_y = d_chatlist_y + d_chatlist_h + 5;
  113. //------------------------------------------------------------------------
  114. // Button Enumerations
  115. //------------------------------------------------------------------------
  116. enum
  117. {
  118. BUTTON_DISCONNECT = 100, // Note: standard WOL button IDs must match values in WolapiObject::PrepareButtonsAndIcons().
  119. BUTTON_LEAVE,
  120. BUTTON_REFRESH,
  121. BUTTON_SQUELCH,
  122. BUTTON_BAN,
  123. BUTTON_KICK,
  124. BUTTON_FINDPAGE,
  125. BUTTON_OPTIONS,
  126. BUTTON_LADDER,
  127. BUTTON_HELP,
  128. BUTTON_CHATLIST,
  129. BUTTON_CHANLIST,
  130. BUTTON_USERLIST,
  131. BUTTON_SENDEDIT,
  132. BUTTON_ACTION,
  133. // BUTTON_CGAME,
  134. BUTTON_CREATE,
  135. BUTTON_JOIN,
  136. BUTTON_BACK,
  137. BUTTON_EXPANDCHANNELS,
  138. BUTTON_EXPANDUSERS,
  139. BUTTON_RANKRA,
  140. BUTTON_RANKAM
  141. };
  142. //------------------------------------------------------------------------
  143. // Redraw values: in order from "top" to "bottom" layer of the dialog
  144. //------------------------------------------------------------------------
  145. typedef enum {
  146. REDRAW_NONE = 0,
  147. REDRAW_BACKGROUND,
  148. REDRAW_ALL = REDRAW_BACKGROUND
  149. } RedrawType;
  150. //------------------------------------------------------------------------
  151. // Dialog variables
  152. //------------------------------------------------------------------------
  153. RedrawType display = REDRAW_ALL; // redraw level
  154. bool process = true; // process while true
  155. KeyNumType input;
  156. TTimerClass<SystemTimerClass> lastclick_timer;
  157. int lastclick_idx = 0; // index of item last clicked on
  158. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  159. //------------------------------------------------------------------------
  160. // Buttons
  161. //------------------------------------------------------------------------
  162. GadgetClass *commands; // button list
  163. char* pShpExpand = (char*)MFCD::Retrieve( "exp.shp" );
  164. char* pShpUnexpand = (char*)MFCD::Retrieve( "unexp.shp" );
  165. IconListClass chatlist( BUTTON_CHATLIST, d_chatlist_x, d_chatlist_y, d_chatlist_w, d_chatlist_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 0, 500 );
  166. ShapeButtonClass ExpandChanBtn( BUTTON_EXPANDCHANNELS, pShpExpand, d_chanlist_x + d_chanlist_w - 17, d_chanlist_y - 14 );
  167. IconListClass chanlist( BUTTON_CHANLIST, d_chanlist_x, d_chanlist_y, d_chanlist_w, d_chanlist_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 1 );
  168. ShapeButtonClass ExpandUserBtn( BUTTON_EXPANDUSERS, pShpExpand, d_userlist_x + d_userlist_w - 17, d_userlist_y - 14 );
  169. IconListClass userlist( BUTTON_USERLIST, d_userlist_x, d_userlist_y, d_userlist_w, d_userlist_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 2 );
  170. TextButtonClass ActionBtn( BUTTON_ACTION, TXT_WOL_ACTION, TPF_BUTTON, d_action_x, d_action_y, d_action_w );
  171. TextButtonClass CreateBtn( BUTTON_CREATE, TXT_WOL_NEWSOMETHING, TPF_BUTTON, d_create_x, d_create_y, d_create_w );
  172. TextButtonClass JoinBtn( BUTTON_JOIN, TXT_WOL_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w );
  173. TextButtonClass BackBtn( BUTTON_BACK, TXT_WOL_BACK, TPF_BUTTON, d_back_x, d_back_y, d_back_w );
  174. char* szRecordToStartWith;
  175. if( pWO->bShowRankRA )
  176. szRecordToStartWith = pWO->szMyRecord;
  177. else
  178. szRecordToStartWith = pWO->szMyRecordAM;
  179. StaticButtonClass chatlistTitle( 0, szRecordToStartWith, TPF_TYPE, d_chatlist_x + 2, d_chatlist_y - 13, d_chatlist_w - 4, 12 );
  180. StaticButtonClass chanlistTitle( 0, "", TPF_TYPE, d_chanlist_x + 2, d_chanlist_y - 16 + 4, d_chanlist_w - 4 - 16, 12 );
  181. StaticButtonClass userlistTitle( 0, TXT_WOL_NOUSERLIST, TPF_TYPE, d_userlist_x + 2, d_userlist_y - 16 + 4, d_userlist_w - 4 - 16 * 4, 12 );
  182. char szSendBuffer[MAXCHATSENDLENGTH] = "";
  183. EditClass sendedit( BUTTON_SENDEDIT, szSendBuffer, MAXCHATSENDLENGTH, TPF_TEXT, d_send_x, d_send_y, d_send_w, d_send_h );
  184. char* pShpRankRA = (char*)MFCD::Retrieve( "rank_ra.shp" );
  185. char* pShpRankAM = (char*)MFCD::Retrieve( "rank_am.shp" );
  186. ShapeButtonClass RankRABtn( BUTTON_RANKRA, pShpRankRA, d_userlist_x + d_userlist_w - ( 16 * 4 + 1 ), d_userlist_y - 14 );
  187. ShapeButtonClass RankAMBtn( BUTTON_RANKAM, pShpRankAM, d_userlist_x + d_userlist_w - ( 16 * 3 + 1 ), d_userlist_y - 14 );
  188. // Change draw behavior of toggle buttons.
  189. RankRABtn.ReflectButtonState = true;
  190. RankAMBtn.ReflectButtonState = true;
  191. // Build the button list.
  192. commands = pWO->pShpBtnDiscon;
  193. pWO->pShpBtnLeave->Add_Tail(*commands);
  194. pWO->pShpBtnRefresh->Add_Tail(*commands);
  195. pWO->pShpBtnSquelch->Add_Tail(*commands);
  196. pWO->pShpBtnBan->Add_Tail(*commands);
  197. pWO->pShpBtnKick->Add_Tail(*commands);
  198. pWO->pShpBtnFindpage->Add_Tail(*commands);
  199. pWO->pShpBtnOptions->Add_Tail(*commands);
  200. pWO->pShpBtnLadder->Add_Tail(*commands);
  201. pWO->pShpBtnHelp->Add_Tail(*commands);
  202. chatlist.Add_Tail(*commands);
  203. ExpandChanBtn.Add_Tail(*commands);
  204. chanlist.Add_Tail(*commands);
  205. ExpandUserBtn.Add_Tail(*commands);
  206. userlist.Add_Tail(*commands);
  207. ActionBtn.Add_Tail(*commands);
  208. CreateBtn.Add_Tail(*commands);
  209. // CreatePrivBtn.Add_Tail(*commands);
  210. JoinBtn.Add_Tail(*commands);
  211. BackBtn.Add_Tail(*commands);
  212. // CGameBtn.Add_Tail(*commands);
  213. chatlistTitle.Add_Tail(*commands);
  214. chanlistTitle.Add_Tail(*commands);
  215. userlistTitle.Add_Tail(*commands);
  216. sendedit.Add_Tail(*commands);
  217. // Tooltips...
  218. DWORD timeToolTipAppear;
  219. ToolTipClass* pToolTipHead = NULL; // Head of list of ToolTips that parallels gadget list.
  220. ToolTipClass* pToolTipHitLast = NULL; // ToolTip the mouse was last over, or null.
  221. ToolTipClass* pToolTip = pToolTipHead = pWO->pTTipDiscon;
  222. pToolTip->next = pWO->pTTipLeave;
  223. pToolTip = pToolTip->next;
  224. pToolTip->next = pWO->pTTipRefresh;
  225. pToolTip = pToolTip->next;
  226. pToolTip->next = pWO->pTTipSquelch;
  227. pToolTip = pToolTip->next;
  228. pToolTip->next = pWO->pTTipBan;
  229. pToolTip = pToolTip->next;
  230. pToolTip->next = pWO->pTTipKick;
  231. pToolTip = pToolTip->next;
  232. pToolTip->next = pWO->pTTipFindpage;
  233. pToolTip = pToolTip->next;
  234. pToolTip->next = pWO->pTTipOptions;
  235. pToolTip = pToolTip->next;
  236. pToolTip->next = pWO->pTTipLadder;
  237. pToolTip = pToolTip->next;
  238. pToolTip->next = pWO->pTTipHelp;
  239. pToolTip = pToolTip->next;
  240. ToolTipClass TTipChanExpand( &ExpandChanBtn, TXT_WOL_TTIP_EXPANDLIST, ExpandChanBtn.X + 8, ExpandChanBtn.Y - 9, true );
  241. pToolTip->next = &TTipChanExpand;
  242. pToolTip = pToolTip->next;
  243. ToolTipClass TTipUserExpand( &ExpandUserBtn, TXT_WOL_TTIP_EXPANDLIST, ExpandUserBtn.X + 8, ExpandUserBtn.Y - 9, true );
  244. pToolTip->next = &TTipUserExpand;
  245. pToolTip = pToolTip->next;
  246. ToolTipClass TTipChanList( &chanlist, 0, chanlist.X + 1, chanlist.Y + 1, true, true );
  247. pToolTip->next = &TTipChanList;
  248. pToolTip = pToolTip->next;
  249. ToolTipClass TTipJoin( &JoinBtn, TXT_WOL_TTIP_JOIN, d_join_x + d_join_w/2, d_join_y - 6 );
  250. pToolTip->next = &TTipJoin;
  251. pToolTip = pToolTip->next;
  252. ToolTipClass TTipBack( &BackBtn, TXT_WOL_TTIP_BACK, d_back_x + d_back_w/2, d_back_y - 6 );
  253. pToolTip->next = &TTipBack;
  254. pToolTip = pToolTip->next;
  255. ToolTipClass TTipCreate( &CreateBtn, TXT_WOL_TTIP_CREATE, d_create_x + d_create_w/2, d_create_y - 6 );
  256. pToolTip->next = &TTipCreate;
  257. pToolTip = pToolTip->next;
  258. ToolTipClass TTipAction( &ActionBtn, TXT_WOL_TTIP_ACTION, d_action_x + d_action_w/2, d_action_y - 6, true );
  259. pToolTip->next = &TTipAction;
  260. pToolTip = pToolTip->next;
  261. ToolTipClass TTipRankRA( &RankRABtn, TXT_WOL_TTIP_RANKRA, RankRABtn.X + 8, RankRABtn.Y - 9, true );
  262. pToolTip->next = &TTipRankRA;
  263. pToolTip = pToolTip->next;
  264. ToolTipClass TTipRankAM( &RankAMBtn, TXT_WOL_TTIP_RANKAM, RankAMBtn.X + 8, RankAMBtn.Y - 9, true );
  265. pToolTip->next = &TTipRankAM;
  266. pToolTip = pToolTip->next;
  267. pToolTip->next = NULL;
  268. //........................................................................
  269. // List boxes
  270. //........................................................................
  271. int tabs[] = { 150 }; // tabs for channel list
  272. chanlist.Set_Tabs( tabs );
  273. // Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_TEXT);
  274. lastclick_timer = 0;
  275. // Tell WolapiObject about lists to use for output.
  276. // (Sure wish I'd gone against the grain and made this dialog a class...)
  277. pWO->LinkToChatDlg( &chatlist, &chanlist, &userlist, &userlistTitle );
  278. if( !pWO->bChatShownBefore )
  279. {
  280. // Print message of the day.
  281. chatlist.Add_Item( pWO->pChatSink->szMotd, NULL, NULL, ICON_SHAPE );
  282. }
  283. else
  284. {
  285. // We have returned to the chat dialog after being in either game setup or an actual game.
  286. pWO->RestoreChat();
  287. pWO->DeleteSavedChat();
  288. if( pWO->bReturningAfterGame )
  289. pWO->RejoinLobbyAfterGame();
  290. else
  291. {
  292. if( pWO->pChatSink->bGotKickedTrigger )
  293. {
  294. // We got kicked out of a game setup.
  295. WOL_PrintMessage( chatlist, TXT_WOL_YOUWEREKICKEDFROMGAME, WOLCOLORREMAP_KICKORBAN );
  296. pWO->pChatSink->bGotKickedTrigger = false;
  297. }
  298. }
  299. if( pWO->iLobbyReturnAfterGame != -1 )
  300. {
  301. char szChannelToJoin[ WOL_CHANNAME_LEN_MAX ];
  302. //sprintf( szChannelToJoin, "Lob_%i_%i", GAME_TYPE, pWO->iLobbyReturnAfterGame );
  303. sprintf( szChannelToJoin, "%s%i", LOB_PREFIX, pWO->iLobbyReturnAfterGame );
  304. pWO->OnEnteringChatChannel( szChannelToJoin, false, iChannelLobbyNumber( (unsigned char*)szChannelToJoin ) );
  305. }
  306. else
  307. // Will never happen presumably, if games are always entered via a lobby chat channel.
  308. pWO->EnterLevel_Top();
  309. pWO->iLobbyReturnAfterGame = -1;
  310. if( pWO->bReturningAfterGame )
  311. {
  312. Sound_Effect( WOLSOUND_LOGIN );
  313. pWO->bReturningAfterGame = false;
  314. }
  315. else
  316. Sound_Effect( WOLSOUND_EXITGAME );
  317. }
  318. // Cause a refresh of szMyRecord, the string showing my win/loss record.
  319. pWO->RequestLadders( pWO->szMyName );
  320. //------------------------------------------------------------------------
  321. // Init Mono Output
  322. //------------------------------------------------------------------------
  323. #if(SHOW_MONO)
  324. Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13);
  325. Ipx.Mono_Debug_Print(-1,1);
  326. #endif
  327. //------------------------------------------------------------------------
  328. // Processing loop
  329. //------------------------------------------------------------------------
  330. while (process)
  331. {
  332. #if(SHOW_MONO)
  333. Ipx.Mono_Debug_Print(-1,0);
  334. #endif
  335. // Regularly check for incoming messages from wolapi.
  336. if( ::timeGetTime() > pWO->dwTimeNextWolapiPump )
  337. {
  338. /*
  339. if( pToolTipHitLast && pToolTipHitLast->bShowing ) // Lame hack. Problem is draws that occur in callbacks.
  340. {
  341. pToolTipHitLast->Unshow();
  342. pWO->pChat->PumpMessages();
  343. pWO->pNetUtil->PumpMessages();
  344. pToolTipHitLast->Show();
  345. }
  346. else
  347. {
  348. pWO->pChat->PumpMessages();
  349. pWO->pNetUtil->PumpMessages();
  350. }
  351. */
  352. pWO->pChat->PumpMessages();
  353. pWO->pNetUtil->PumpMessages();
  354. // Special post-callback processing...
  355. if( pWO->bSelfDestruct )
  356. {
  357. if( pWO->pChatSink->bConnected )
  358. pWO->Logout();
  359. rc = -1; // As if the user logged himself out.
  360. process = false;
  361. break;
  362. }
  363. if( pWO->pChatSink->bGotKickedTrigger )
  364. {
  365. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  366. {
  367. pWO->OnExitingChatChannel();
  368. pWO->EnterLevel_UserChat();
  369. }
  370. else if( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  371. {
  372. pWO->OnExitingChatChannel();
  373. pWO->EnterLevel_Lobbies();
  374. }
  375. else // Must be WOL_LEVEL_INOFFICIALCHATCHANNEL.
  376. {
  377. pWO->OnExitingChatChannel();
  378. pWO->EnterLevel_OfficialChat();
  379. }
  380. pWO->pChatSink->bGotKickedTrigger = false;
  381. display = REDRAW_ALL;
  382. }
  383. if( pWO->bMyRecordUpdated )
  384. {
  385. if( pWO->bShowRankRA )
  386. chatlistTitle.Set_Text( pWO->szMyRecord );
  387. else
  388. chatlistTitle.Set_Text( pWO->szMyRecordAM );
  389. pWO->bMyRecordUpdated = false;
  390. }
  391. if( pWO->bChannelListTitleUpdated )
  392. {
  393. chanlistTitle.Set_Text( pWO->szChannelListTitle );
  394. pWO->bChannelListTitleUpdated = false;
  395. }
  396. pWO->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;
  397. }
  398. // Synch rank toggle buttons state.
  399. if( BackBtn.Get_Prev() == &RankAMBtn )
  400. {
  401. if( pWO->CurrentLevel != WOL_LEVEL_INLOBBY )
  402. {
  403. // Rank buttons are there and shouldn't be.
  404. RankRABtn.Remove();
  405. RankAMBtn.Remove();
  406. display = REDRAW_ALL;
  407. }
  408. else
  409. {
  410. if( pWO->bShowRankUpdated )
  411. {
  412. if( pWO->bShowRankRA )
  413. {
  414. RankRABtn.DRAWTOGDOWN;
  415. RankAMBtn.DRAWTOGUP;
  416. }
  417. else
  418. {
  419. RankRABtn.DRAWTOGUP;
  420. RankAMBtn.DRAWTOGDOWN;
  421. }
  422. // Buttons have been refreshed.
  423. pWO->bShowRankUpdated = false;
  424. // Cause my own record to get refreshed.
  425. pWO->bMyRecordUpdated = true;
  426. // Refresh list to show different rankings type.
  427. pWO->ListChannelUsers();
  428. }
  429. }
  430. }
  431. else
  432. {
  433. if( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  434. {
  435. // Rank buttons aren't there and should be.
  436. RankRABtn.Add( JoinBtn );
  437. RankAMBtn.Add( RankRABtn );
  438. RankRABtn.Flag_To_Redraw();
  439. RankAMBtn.Flag_To_Redraw();
  440. if( pWO->bShowRankRA )
  441. {
  442. RankRABtn.DRAWTOGDOWN;
  443. RankAMBtn.DRAWTOGUP;
  444. }
  445. else
  446. {
  447. RankRABtn.DRAWTOGUP;
  448. RankAMBtn.DRAWTOGDOWN;
  449. }
  450. // Buttons have been refreshed.
  451. pWO->bShowRankUpdated = false;
  452. }
  453. }
  454. // Regularly update the channels list in certain cases.
  455. if( ( pWO->CurrentLevel == WOL_LEVEL_OFFICIALCHAT || pWO->CurrentLevel == WOL_LEVEL_USERCHAT ||
  456. pWO->CurrentLevel == WOL_LEVEL_LOBBIES || pWO->CurrentLevel == WOL_LEVEL_INLOBBY ) &&
  457. ::timeGetTime() > pWO->dwTimeNextChannelUpdate )
  458. {
  459. switch( pWO->CurrentLevel )
  460. {
  461. case WOL_LEVEL_OFFICIALCHAT:
  462. pWO->UpdateChannels( 0, CHANNELFILTER_OFFICIAL, false );
  463. break;
  464. case WOL_LEVEL_USERCHAT:
  465. pWO->UpdateChannels( 0, CHANNELFILTER_UNOFFICIAL, false );
  466. break;
  467. case WOL_LEVEL_LOBBIES: // Overkill in this case to update so often...
  468. pWO->UpdateChannels( 0, CHANNELFILTER_LOBBIES, false );
  469. break;
  470. case WOL_LEVEL_INLOBBY:
  471. pWO->UpdateChannels( GAME_TYPE, CHANNELFILTER_LOCALLOBBYGAMES, true );
  472. break;
  473. }
  474. pWO->dwTimeNextChannelUpdate = ::timeGetTime() + CHANNELUPDATEWAIT;
  475. }
  476. #ifdef WIN32
  477. /*
  478. ** If we have just received input focus again after running in the background then
  479. ** we need to redraw.
  480. */
  481. if (AllSurfaces.SurfacesRestored) {
  482. AllSurfaces.SurfacesRestored=FALSE;
  483. display = REDRAW_ALL;
  484. }
  485. #endif
  486. if( bFirsttime && !pWO->bChatShownBefore )
  487. {
  488. WWMessageBox().Process( TXT_WOL_FINDINGLOBBY, TXT_NONE );
  489. char szLobbyName[ WOL_CHANNAME_LEN_MAX ];
  490. if( pWO->GetNameOfBeginningLobby( szLobbyName ) )
  491. {
  492. // debugprint( "Found lobby to go into: '%s'\n", szLobbyName );
  493. if( !EnterChannel( pWO, chatlist, NULL, szLobbyName, false ) )
  494. {
  495. // Could not enter channel for some reason. Go to top instead.
  496. pWO->EnterLevel_Top();
  497. }
  498. }
  499. else
  500. {
  501. // Could not find name of a lobby for some reason. Go to top instead.
  502. pWO->EnterLevel_Top();
  503. }
  504. pWO->bChatShownBefore = true;
  505. display = REDRAW_ALL;
  506. // Play login sound.
  507. Sound_Effect( WOLSOUND_LOGIN );
  508. }
  509. bFirsttime = false;
  510. //.....................................................................
  511. // Refresh display if needed
  512. //.....................................................................
  513. if (display)
  514. {
  515. Hide_Mouse();
  516. //..................................................................
  517. // Redraw backgound & dialog box
  518. //..................................................................
  519. if (display >= REDRAW_BACKGROUND)
  520. {
  521. if( pToolTipHitLast && pToolTipHitLast->bShowing )
  522. {
  523. pToolTipHitLast->Unshow();
  524. }
  525. Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
  526. //...............................................................
  527. // Dialog & Field labels
  528. //...............................................................
  529. commands->Draw_All();
  530. // Draw title bar above channel list.
  531. Draw_Box( d_chanlist_x, d_chanlist_y - 15, d_chanlist_w, 16, BOXSTYLE_BOX, false );
  532. switch( lesCurrent )
  533. {
  534. case LES_CHANNELS_EXPANDED:
  535. // Draw users title bar at bottom.
  536. Draw_Box( d_userlist_x, d_userlist_y + d_userlist_h - 16, d_userlist_w, 16, BOXSTYLE_BOX, false );
  537. break;
  538. case LES_USERS_EXPANDED:
  539. // Draw users title bar at top.
  540. Draw_Box( d_chanlist_x, d_chanlist_y, d_chanlist_w, 16, BOXSTYLE_BOX, false );
  541. break;
  542. default:
  543. // Draw users title bar in middle.
  544. Draw_Box( d_userlist_x, d_userlist_y - 15, d_userlist_w, 16, BOXSTYLE_BOX, false );
  545. break;
  546. }
  547. }
  548. Show_Mouse();
  549. display = REDRAW_NONE;
  550. }
  551. // Force mouse visible, as some beta testers report unexplicable disappearing cursors.
  552. while( Get_Mouse_State() )
  553. Show_Mouse();
  554. // Be nice to other apps.
  555. Sleep( 50 );
  556. //.....................................................................
  557. // Get user input
  558. //.....................................................................
  559. if( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) )
  560. {
  561. // Mouse button is down.
  562. timeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;
  563. if( pToolTipHitLast && pToolTipHitLast->bShowing )
  564. {
  565. pToolTipHitLast->Unshow();
  566. }
  567. }
  568. // If anything currently on the controls list is set to redraw, hide tooltip.
  569. if( pToolTipHitLast && pToolTipHitLast->bShowing && commands->Is_List_To_Redraw() )
  570. {
  571. pToolTipHitLast->Unshow();
  572. }
  573. input = commands->Input();
  574. // This hack, used elsewhere in this form, appears to be the standard dodge around GadgetClass::Input's
  575. // tendency to remove any focus the first time it runs for a 'commands' list.
  576. // ajw - Perhaps I could try doing this every cycle regardless - would avoid stupid non-focused editbox key reactions bug.
  577. if( bHackFocus )
  578. {
  579. sendedit.Set_Focus();
  580. sendedit.Flag_To_Redraw();
  581. input = commands->Input();
  582. bHackFocus = false;
  583. }
  584. // Tooltips...
  585. if( pToolTipHead )
  586. {
  587. ToolTipClass* pToolTipHit = pToolTipHead->GetToolTipHit();
  588. if( pToolTipHit == pToolTipHitLast )
  589. {
  590. if( pToolTipHit && bLinkInList( commands, pToolTipHit->pGadget ) ) // (Gadget must be in controls list.)
  591. {
  592. if( !pToolTipHit->bShowing && ::timeGetTime() > timeToolTipAppear &&
  593. !( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) ) )
  594. {
  595. pToolTipHit->Show();
  596. }
  597. else if( pToolTipHit->bIconList && pToolTipHit->bOverDifferentLine() )
  598. {
  599. pToolTipHit->Unshow();
  600. pToolTipHit->Show();
  601. }
  602. }
  603. }
  604. else
  605. {
  606. if( pToolTipHitLast && pToolTipHitLast->bShowing )
  607. pToolTipHitLast->Unshow();
  608. pToolTipHitLast = pToolTipHit;
  609. timeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;
  610. }
  611. }
  612. //.....................................................................
  613. // Process input
  614. //.....................................................................
  615. switch (input)
  616. {
  617. case ( BUTTON_SENDEDIT | KN_BUTTON ):
  618. // Enter has been pressed - was caught by sendedit control.
  619. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  620. {
  621. pWO->SendMessage( sendedit.Get_Text(), userlist, false );
  622. // Clear sendedit, reset focus.
  623. szSendBuffer[0] = 0;
  624. sendedit.Set_Focus();
  625. // Mark for redraw.
  626. sendedit.Flag_To_Redraw();
  627. }
  628. else
  629. {
  630. WOL_PrintMessage( chatlist, TXT_WOL_YOURENOTINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );
  631. Sound_Effect( WOLSOUND_ERROR );
  632. sendedit.Set_Focus();
  633. // Mark for redraw.
  634. sendedit.Flag_To_Redraw();
  635. }
  636. break;
  637. case KN_LMOUSE:
  638. break;
  639. case ( BUTTON_EXPANDCHANNELS | KN_BUTTON ):
  640. if( OnExpandChannelList( chanlist, userlist ) )
  641. {
  642. // Hide userlist.
  643. if( ExpandUserBtn.Get_Next() == &userlist )
  644. userlist.Remove();
  645. // Ensure chanlist is visible.
  646. if( ExpandChanBtn.Get_Next() != &chanlist )
  647. chanlist.Add( ExpandChanBtn );
  648. // Move userlist expand button.
  649. ExpandUserBtn.Set_Position( ExpandUserBtn.X, chanlist.Y + chanlist.Height );
  650. TTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );
  651. userlistTitle.Set_Position( userlistTitle.X, chanlist.Y + chanlist.Height + 2 );
  652. // Set buttons.
  653. ExpandChanBtn.Set_Shape( pShpUnexpand );
  654. ExpandUserBtn.Set_Shape( pShpExpand );
  655. }
  656. else
  657. {
  658. // Show userlist.
  659. if( ExpandUserBtn.Get_Next() != &userlist )
  660. userlist.Add( ExpandUserBtn );
  661. // Move userlist expand button.
  662. ExpandUserBtn.Set_Position( ExpandUserBtn.X, userlist.Y - 14 );
  663. TTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );
  664. userlistTitle.Set_Position( userlistTitle.X, userlist.Y - 16 + 4 );
  665. // Set buttons.
  666. ExpandChanBtn.Set_Shape( pShpExpand );
  667. ExpandUserBtn.Set_Shape( pShpExpand );
  668. }
  669. // Move rank buttons.
  670. RankRABtn.Set_Position( RankRABtn.X, ExpandUserBtn.Y );
  671. RankAMBtn.Set_Position( RankAMBtn.X, ExpandUserBtn.Y );
  672. TTipRankRA.Move( RankRABtn.X + 8, RankRABtn.Y - 16 );
  673. TTipRankAM.Move( RankAMBtn.X + 8, RankAMBtn.Y - 16 );
  674. display = REDRAW_ALL;
  675. break;
  676. case ( BUTTON_EXPANDUSERS | KN_BUTTON ):
  677. if( OnExpandUserList( chanlist, userlist ) )
  678. {
  679. // Hide chanlist controls.
  680. if( ExpandChanBtn.Get_Next() == &chanlist )
  681. chanlist.Remove();
  682. // Ensure userlist is visible.
  683. if( ExpandUserBtn.Get_Next() != &userlist )
  684. userlist.Add( ExpandUserBtn );
  685. // Set buttons.
  686. ExpandChanBtn.Set_Shape( pShpExpand );
  687. ExpandUserBtn.Set_Shape( pShpUnexpand );
  688. }
  689. else
  690. {
  691. // Show chanlist.
  692. if( ExpandChanBtn.Get_Next() != &chanlist )
  693. chanlist.Add( ExpandChanBtn );
  694. // Set buttons.
  695. ExpandChanBtn.Set_Shape( pShpExpand );
  696. ExpandUserBtn.Set_Shape( pShpExpand );
  697. }
  698. // Move userlist expand button.
  699. ExpandUserBtn.Set_Position( ExpandUserBtn.X, userlist.Y - 14 );
  700. TTipUserExpand.Move( ExpandUserBtn.X + 8, ExpandUserBtn.Y - 16 );
  701. userlistTitle.Set_Position( userlistTitle.X, userlist.Y - 16 + 4 );
  702. // Move rank buttons.
  703. RankRABtn.Set_Position( RankRABtn.X, ExpandUserBtn.Y );
  704. RankAMBtn.Set_Position( RankAMBtn.X, ExpandUserBtn.Y );
  705. TTipRankRA.Move( RankRABtn.X + 8, RankRABtn.Y - 16 );
  706. TTipRankAM.Move( RankAMBtn.X + 8, RankAMBtn.Y - 16 );
  707. display = REDRAW_ALL;
  708. break;
  709. case ( BUTTON_CHANLIST | KN_BUTTON ):
  710. // User clicks on the game list.
  711. //...............................................................
  712. // Handle a double-click
  713. //...............................................................
  714. if( lastclick_timer < 30 && chanlist.Current_Index() == lastclick_idx )
  715. {
  716. // Doubleclick on channel list.
  717. if( ProcessChannelListSelection( pWO, chatlist, chanlist, lastclick_idx ) )
  718. {
  719. // Exit the chat dialog, go to game dialog.
  720. rc = 2;
  721. process = false;
  722. }
  723. display = REDRAW_ALL;
  724. bHackFocus = true;
  725. }
  726. else
  727. {
  728. //...............................................................
  729. // Handle a single-click
  730. //...............................................................
  731. //............................................................
  732. // If no double-click occurred, set the last-clicked index
  733. // & double-click timer.
  734. //............................................................
  735. lastclick_timer = 0;
  736. lastclick_idx = chanlist.Current_Index();
  737. }
  738. break;
  739. case ( BUTTON_JOIN | KN_BUTTON ):
  740. // Pressing the join button is exactly like doubleclicking on the selected index in chanlist, except:
  741. // if the first item is selected, ignore, unless we are at the top level
  742. if( pWO->CurrentLevel == WOL_LEVEL_TOP || chanlist.Current_Index() != 0 )
  743. {
  744. if( ProcessChannelListSelection( pWO, chatlist, chanlist, chanlist.Current_Index() ) )
  745. {
  746. // Exit the chat dialog, go to game dialog.
  747. rc = 2;
  748. process = false;
  749. }
  750. display = REDRAW_ALL;
  751. bHackFocus = true;
  752. }
  753. break;
  754. case ( BUTTON_USERLIST | KN_BUTTON ):
  755. // User clicks on user list.
  756. break;
  757. case ( BUTTON_CREATE | KN_BUTTON ):
  758. switch( pWO->CurrentLevel )
  759. {
  760. case WOL_LEVEL_INCHATCHANNEL:
  761. // debugprint( "%s\n", TXT_WOL_CANTCREATEINCHANNEL );
  762. WOL_PrintMessage( chatlist, TXT_WOL_CANTCREATEINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );
  763. Sound_Effect( WOLSOUND_ERROR );
  764. break;
  765. case WOL_LEVEL_INLOBBY:
  766. {
  767. pWO->bPump_In_Call_Back = true;
  768. CREATEGAMEINFO CreateGameInfo = WOL_CreateGame_Dialog( pWO );
  769. pWO->bPump_In_Call_Back = false;
  770. if( CreateGameInfo.bCreateGame )
  771. {
  772. if( CreateGameChannel( pWO, CreateGameInfo ) )
  773. {
  774. rc = 1;
  775. process = false;
  776. }
  777. }
  778. break;
  779. }
  780. case WOL_LEVEL_GAMES:
  781. case WOL_LEVEL_GAMESOFTYPE:
  782. case WOL_LEVEL_LOBBIES:
  783. WOL_PrintMessage( chatlist, TXT_WOL_CANTCREATEHERE, WOLCOLORREMAP_LOCALMACHINEMESS );
  784. Sound_Effect( WOLSOUND_ERROR );
  785. break;
  786. default:
  787. CreateChatChannel( pWO );
  788. }
  789. display = REDRAW_ALL;
  790. bHackFocus = true;
  791. break;
  792. case ( BUTTON_LEAVE | KN_BUTTON ):
  793. // Because of the way things are set up, this is exactly like selecting the first item in chanlist.
  794. // (Button is disabled when this is not appropriate.)
  795. ProcessChannelListSelection( pWO, chatlist, chanlist, 0 );
  796. display = REDRAW_ALL;
  797. break;
  798. case ( BUTTON_REFRESH | KN_BUTTON ):
  799. pWO->dwTimeNextChannelUpdate = ::timeGetTime();
  800. break;
  801. case ( BUTTON_SQUELCH | KN_BUTTON ):
  802. pWO->DoSquelch( &userlist );
  803. break;
  804. case ( BUTTON_BAN | KN_BUTTON ):
  805. pWO->DoKick( &userlist, true );
  806. // display = REDRAW_ALL;
  807. break;
  808. case ( BUTTON_KICK | KN_BUTTON ):
  809. pWO->DoKick( &userlist, false );
  810. // display = REDRAW_ALL;
  811. break;
  812. case ( BUTTON_FINDPAGE | KN_BUTTON ):
  813. pWO->DoFindPage();
  814. display = REDRAW_ALL;
  815. bHackFocus = true;
  816. break;
  817. case ( BUTTON_OPTIONS | KN_BUTTON ):
  818. pWO->DoOptions();
  819. display = REDRAW_ALL;
  820. bHackFocus = true;
  821. break;
  822. case ( KN_ESC ):
  823. // break; ajw Put back in?
  824. case ( BUTTON_BACK | KN_BUTTON ):
  825. // Pressing the back button is exactly like doubleclicking on the top item in chanlist, except
  826. // when we're at the top level.
  827. if( pWO->CurrentLevel != WOL_LEVEL_TOP )
  828. {
  829. ProcessChannelListSelection( pWO, chatlist, chanlist, 0 );
  830. display = REDRAW_ALL;
  831. break;
  832. }
  833. // Note no break; here. Fall through if at top level.
  834. case ( BUTTON_DISCONNECT | KN_BUTTON ):
  835. if( WWMessageBox().Process( TXT_WOL_CONFIRMLOGOUT, TXT_YES, TXT_NO ) == 0 )
  836. {
  837. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  838. ExitChatChannel( pWO );
  839. pWO->Logout();
  840. rc = -1;
  841. process = false;
  842. }
  843. display = REDRAW_ALL;
  844. bHackFocus = true;
  845. break;
  846. case ( BUTTON_ACTION | KN_BUTTON ):
  847. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  848. {
  849. pWO->SendMessage( sendedit.Get_Text(), userlist, true );
  850. // Clear sendedit, reset focus.
  851. szSendBuffer[0] = 0;
  852. sendedit.Set_Focus();
  853. // Mark for redraw.
  854. //chatlist.Flag_To_Redraw();
  855. sendedit.Flag_To_Redraw();
  856. }
  857. else
  858. {
  859. WOL_PrintMessage( chatlist, TXT_WOL_YOURENOTINCHANNEL, WOLCOLORREMAP_LOCALMACHINEMESS );
  860. Sound_Effect( WOLSOUND_ERROR );
  861. sendedit.Set_Focus();
  862. // Mark for redraw.
  863. sendedit.Flag_To_Redraw();
  864. }
  865. break;
  866. case ( BUTTON_LADDER | KN_BUTTON ):
  867. pWO->DoLadder();
  868. display = REDRAW_ALL;
  869. bHackFocus = true;
  870. break;
  871. case ( BUTTON_HELP | KN_BUTTON ):
  872. pWO->DoHelp();
  873. display = REDRAW_ALL;
  874. bHackFocus = true;
  875. break;
  876. case ( BUTTON_RANKRA | KN_BUTTON ):
  877. pWO->bShowRankRA = true;
  878. pWO->bShowRankUpdated = true;
  879. break;
  880. case ( BUTTON_RANKAM | KN_BUTTON ):
  881. pWO->bShowRankRA = false;
  882. pWO->bShowRankUpdated = true;
  883. break;
  884. default:
  885. break;
  886. }
  887. //.....................................................................
  888. // Service the sounds & score; GameActive must be false at this point,
  889. // so Call_Back() doesn't intercept global messages from me!
  890. //.....................................................................
  891. Call_Back();
  892. } // end of while
  893. if( pToolTipHitLast && pToolTipHitLast->bShowing )
  894. pToolTipHitLast->Unshow();
  895. /*
  896. //------------------------------------------------------------------------
  897. // Restore screen
  898. //------------------------------------------------------------------------
  899. Hide_Mouse();
  900. Load_Title_Page(true);
  901. Show_Mouse();
  902. */
  903. pWO->SaveChat();
  904. pWO->ClearListPtrs();
  905. return rc;
  906. }
  907. //***********************************************************************************************
  908. void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap /* = PCOLOR_NONE */ )
  909. {
  910. RemapControlType* pColorRemap = ( iColorRemap == PCOLOR_NONE ? NULL : &ColorRemaps[ iColorRemap ] );
  911. WOL_PrintMessage( ILTarget, szText, pColorRemap );
  912. }
  913. //***********************************************************************************************
  914. void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap )
  915. {
  916. ILTarget.Add_Item( szText, NULL, NULL, ICON_SHAPE, NULL, NULL, pColorRemap );
  917. if( !ILTarget.bScrollBeingDragged() )
  918. ILTarget.Show_Last_Item();
  919. }
  920. //***********************************************************************************************
  921. bool OnExpandChannelList( IconListClass& chanlist, IconListClass& userlist )
  922. {
  923. // Expand channel list button was pressed.
  924. // Returns true if userlist controls are to be hidden, false if they are to be shown.
  925. switch( lesCurrent )
  926. {
  927. case LES_NORMAL:
  928. ResizeChannelList( chanlist, true );
  929. lesCurrent = LES_CHANNELS_EXPANDED;
  930. break;
  931. case LES_USERS_EXPANDED:
  932. ResizeUserList( userlist, false );
  933. ResizeChannelList( chanlist, true );
  934. lesCurrent = LES_CHANNELS_EXPANDED;
  935. break;
  936. case LES_CHANNELS_EXPANDED:
  937. ResizeChannelList( chanlist, false );
  938. lesCurrent = LES_NORMAL;
  939. return false;
  940. }
  941. return true;
  942. }
  943. //***********************************************************************************************
  944. bool OnExpandUserList( IconListClass& chanlist, IconListClass& userlist )
  945. {
  946. // Expand user list button was pressed.
  947. // Returns true if chanlist controls are to be hidden, false if they are to be shown.
  948. switch( lesCurrent )
  949. {
  950. case LES_NORMAL:
  951. ResizeUserList( userlist, true );
  952. lesCurrent = LES_USERS_EXPANDED;
  953. break;
  954. case LES_CHANNELS_EXPANDED:
  955. ResizeChannelList( chanlist, false );
  956. ResizeUserList( userlist, true );
  957. lesCurrent = LES_USERS_EXPANDED;
  958. break;
  959. case LES_USERS_EXPANDED:
  960. ResizeUserList( userlist, false );
  961. lesCurrent = LES_NORMAL;
  962. return false;
  963. }
  964. return true;
  965. }
  966. //***********************************************************************************************
  967. void ResizeChannelList( IconListClass& chanlist, bool bExpand )
  968. {
  969. // If bExpand, makes list big, else normal size.
  970. if( bExpand )
  971. chanlist.Resize( d_chanlist_x, d_chanlist_y, d_chanlist_w, d_userlist_y + d_userlist_h - 15 - d_chanlist_y );
  972. else
  973. chanlist.Resize( d_chanlist_x, d_chanlist_y, d_chanlist_w, d_chanlist_h );
  974. }
  975. //***********************************************************************************************
  976. void ResizeUserList( IconListClass& userlist, bool bExpand )
  977. {
  978. // If bExpand, makes list big, else normal size.
  979. if( bExpand )
  980. userlist.Resize( d_userlist_x, d_chanlist_y + 15, d_userlist_w, d_userlist_y + d_userlist_h - ( d_chanlist_y + 15 ) );
  981. else
  982. userlist.Resize( d_userlist_x, d_userlist_y, d_userlist_w, d_userlist_h );
  983. }
  984. //***********************************************************************************************
  985. bool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex, bool bGame )
  986. {
  987. // Enter the channel specified in chanlist at iIndex.
  988. // Called to enter chat channels, "lobbies", and game channels.
  989. // We've stored the channel pointer in the hidden extra data field.
  990. // ( Be careful about calling RAChatEventSink::DeleteChannelList()! )
  991. Channel* pChannel = (Channel*)chanlist.Get_Item_ExtraDataPtr( iIndex );
  992. return EnterChannel( pWO, chatlist, pChannel, NULL, bGame );
  993. }
  994. //***********************************************************************************************
  995. bool EnterChannel( WolapiObject* pWO, IconListClass& chatlist, Channel* pChannel, char* szChannelName, bool bGame )
  996. {
  997. // Called to cause the user to enter a channel (chat, lobby, or game).
  998. // If pChannel is NULL, szChannelName will be used.
  999. Channel ChannelWhenNameOnly;
  1000. if( !pChannel )
  1001. {
  1002. if( !szChannelName )
  1003. {
  1004. // debugprint( "pChannel and szChannelName null in EnterChannel" );
  1005. pWO->bSelfDestruct = true;
  1006. return false;
  1007. }
  1008. pChannel = &ChannelWhenNameOnly;
  1009. strcpy( (char*)pChannel->name, szChannelName );
  1010. }
  1011. if( bGame && pChannel->currentUsers >= pChannel->maxUsers ) // Pre-emptive fullness check.
  1012. {
  1013. WOL_PrintMessage( chatlist, TXT_WOL_CHANNELFULL, WOLCOLORREMAP_LOCALMACHINEMESS );
  1014. Sound_Effect( WOLSOUND_ERROR );
  1015. return false;
  1016. }
  1017. if( bGame )
  1018. {
  1019. // It is possible to enter a game channel while currently in a chat channel. (A lobby, presumably.)
  1020. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  1021. if( !pWO->ExitChatChannelForGameChannel() )
  1022. {
  1023. *pWO->szChannelReturnOnGameEnterFail = 0;
  1024. // debugprint( "ExitChatChannelForGameChannel on join failed" );
  1025. pWO->bSelfDestruct = true;
  1026. return false;
  1027. }
  1028. }
  1029. /* The following doesn't work because the needpw field is not currently being set in wolapi for chat channels.
  1030. Instead, we wait for a fail on join, then present this dialog and try again.
  1031. if( pChannel->needpw )
  1032. {
  1033. SimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,
  1034. WOL_CHANKEY_LEN_MAX );
  1035. if( !pEditDlg->Show() || !*pEditDlg->szEdit )
  1036. return false;
  1037. strcpy( (char*)pChannel->key, pEditDlg->szEdit );
  1038. }
  1039. */
  1040. bool bKeepTrying = true;
  1041. // Set password automatically for our lobbies, if trying to join one.
  1042. int iLobby = iChannelLobbyNumber( pChannel->name );
  1043. if( iLobby != -1 )
  1044. strcpy( (char*)pChannel->key, LOBBYPASSWORD );
  1045. char szSuccessfulPassword[ WOL_PASSWORD_LEN + 5 ];
  1046. *szSuccessfulPassword = 0;
  1047. HRESULT hRes;
  1048. while( bKeepTrying )
  1049. {
  1050. hRes = pWO->ChannelJoin( pChannel );
  1051. switch( hRes )
  1052. {
  1053. case CHAT_E_BADCHANNELPASSWORD:
  1054. {
  1055. Fancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT ); // Required before String_Pixel_Width() call, for god's sake.
  1056. #ifdef ENGLISH
  1057. SimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,
  1058. WOL_CHANKEY_LEN_MAX );
  1059. #else
  1060. #ifdef GERMAN
  1061. SimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 400, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,
  1062. WOL_CHANKEY_LEN_MAX );
  1063. #else
  1064. SimpleEditDlgClass* pEditDlg = new SimpleEditDlgClass( 500, TXT_WOL_JOINPRIVATETITLE, TXT_WOL_JOINPRIVATEPROMPT,
  1065. WOL_CHANKEY_LEN_MAX );
  1066. #endif
  1067. #endif
  1068. pWO->bPump_In_Call_Back = true;
  1069. if( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) != 0 || !*pEditDlg->szEdit )
  1070. {
  1071. pWO->bPump_In_Call_Back = false;
  1072. delete pEditDlg;
  1073. bKeepTrying = false;
  1074. break;
  1075. }
  1076. pWO->bPump_In_Call_Back = false;
  1077. strcpy( (char*)pChannel->key, pEditDlg->szEdit );
  1078. strcpy( szSuccessfulPassword, pEditDlg->szEdit );
  1079. delete pEditDlg;
  1080. break;
  1081. }
  1082. case CHAT_E_TIMEOUT:
  1083. pWO->bPump_In_Call_Back = true;
  1084. WWMessageBox().Process( TXT_WOL_TIMEOUT );
  1085. pWO->bPump_In_Call_Back = false;
  1086. bKeepTrying = false;
  1087. break;
  1088. case CHAT_E_CHANNELDOESNOTEXIST:
  1089. pWO->bPump_In_Call_Back = true;
  1090. WWMessageBox().Process( TXT_WOL_CHANNELGONE );
  1091. pWO->bPump_In_Call_Back = false;
  1092. bKeepTrying = false;
  1093. break;
  1094. case CHAT_E_BANNED:
  1095. WOL_PrintMessage( chatlist, TXT_WOL_YOUREBANNED, WOLCOLORREMAP_LOCALMACHINEMESS );
  1096. Sound_Effect( WOLSOUND_ERROR );
  1097. bKeepTrying = false;
  1098. break;
  1099. case CHAT_E_CHANNELFULL:
  1100. WOL_PrintMessage( chatlist, TXT_WOL_CHANNELFULL, WOLCOLORREMAP_LOCALMACHINEMESS );
  1101. Sound_Effect( WOLSOUND_ERROR );
  1102. bKeepTrying = false;
  1103. break;
  1104. case E_FAIL:
  1105. pWO->GenericErrorMessage();
  1106. bKeepTrying = false;
  1107. break;
  1108. case S_OK:
  1109. bKeepTrying = false;
  1110. break;
  1111. }
  1112. }
  1113. if( !bGame )
  1114. {
  1115. if( hRes == S_OK )
  1116. return pWO->OnEnteringChatChannel( (char*)pChannel->name, false, iLobby );
  1117. else
  1118. return false;
  1119. }
  1120. else
  1121. {
  1122. if( hRes == S_OK )
  1123. {
  1124. *pWO->szChannelReturnOnGameEnterFail = 0;
  1125. // Return later to the lobby of the channel creator - which was saved in the channel itself.
  1126. pWO->iLobbyReturnAfterGame = pChannel->reserved & 0x00FFFFFF;
  1127. if( pWO->iLobbyReturnAfterGame == 0x00FFFFFF )
  1128. pWO->iLobbyReturnAfterGame = -1;
  1129. CREATEGAMEINFO CreateGameInfo;
  1130. // Not all of these values are currently used during setup.
  1131. CreateGameInfo.bCreateGame = false;
  1132. CreateGameInfo.iPlayerMax = pChannel->maxUsers;
  1133. CreateGameInfo.bTournament = pChannel->tournament;
  1134. if( *szSuccessfulPassword )
  1135. {
  1136. CreateGameInfo.bPrivate = true;
  1137. strcpy( CreateGameInfo.szPassword, szSuccessfulPassword );
  1138. }
  1139. else
  1140. {
  1141. CreateGameInfo.bPrivate = false;
  1142. *CreateGameInfo.szPassword = 0;
  1143. }
  1144. CreateGameInfo.GameKind = (CREATEGAMEINFO::GAMEKIND)( pChannel->reserved & 0xFF000000 );
  1145. return pWO->OnEnteringGameChannel( (char*)pChannel->name, false, CreateGameInfo );
  1146. }
  1147. else
  1148. {
  1149. pWO->OnFailedToEnterGameChannel();
  1150. *pWO->szChannelReturnOnGameEnterFail = 0;
  1151. return false;
  1152. }
  1153. }
  1154. }
  1155. //***********************************************************************************************
  1156. bool ExitChatChannel( WolapiObject* pWO )
  1157. {
  1158. // Called to cause user to leave current chat or lobby channel.
  1159. // debugprint( "ExitChatChannel\n" );
  1160. if( !pWO->ChannelLeave() )
  1161. {
  1162. pWO->GenericErrorMessage();
  1163. return false;
  1164. }
  1165. pWO->OnExitingChatChannel();
  1166. return true;
  1167. }
  1168. //***********************************************************************************************
  1169. //void CreateChatChannel( WolapiObject* pWO, bool bPrivate )
  1170. void CreateChatChannel( WolapiObject* pWO )
  1171. {
  1172. SimpleEditDlgClass* pEditDlg;
  1173. /* if( !bPrivate )
  1174. {
  1175. pEditDlg = new SimpleEditDlgClass( 300, TXT_WOL_CREATECHANNELTITLE, TXT_WOL_CREATECHANNELPROMPT,
  1176. WOL_CHANNAME_LEN_MAX );
  1177. if( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pEditDlg->szEdit )
  1178. {
  1179. if( pWO->ChannelCreate( pEditDlg->szEdit, NULL ) )
  1180. pWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );
  1181. }
  1182. }
  1183. else
  1184. */ {
  1185. Fancy_Text_Print( TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT ); // Required before String_Pixel_Width() call, for god's sake.
  1186. pEditDlg = new SimpleEditDlgClass( 350, TXT_WOL_CREATECHANNELTITLE, TXT_WOL_CREATECHANNELPROMPT,
  1187. WOL_CHANNAME_LEN_MAX, TXT_WOL_OPTIONALPASSPROMPT, WOL_CHANKEY_LEN_MAX );
  1188. pWO->bPump_In_Call_Back = true;
  1189. if( strcmp( pEditDlg->Show(), Text_String( TXT_OK ) ) == 0 && *pEditDlg->szEdit )
  1190. {
  1191. pWO->bPump_In_Call_Back = false;
  1192. if( *pEditDlg->szEdit2 )
  1193. {
  1194. if( pWO->ChannelCreate( pEditDlg->szEdit, pEditDlg->szEdit2 ) )
  1195. pWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );
  1196. }
  1197. else
  1198. {
  1199. // Create public channel.
  1200. if( pWO->ChannelCreate( pEditDlg->szEdit, NULL ) )
  1201. pWO->OnEnteringChatChannel( pEditDlg->szEdit, true, -1 );
  1202. }
  1203. }
  1204. pWO->bPump_In_Call_Back = false;
  1205. }
  1206. delete pEditDlg;
  1207. }
  1208. //***********************************************************************************************
  1209. bool CreateGameChannel( WolapiObject* pWO, const CREATEGAMEINFO& cgi )
  1210. {
  1211. char szNewChannelName[ WOL_CHANNAME_LEN_MAX ];
  1212. sprintf( szNewChannelName, "%s's_game", pWO->szMyName );
  1213. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL || pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  1214. if( !pWO->ExitChatChannelForGameChannel() )
  1215. {
  1216. *pWO->szChannelReturnOnGameEnterFail = 0;
  1217. // debugprint( "ExitChatChannelForGameChannel in CreateGameChannel() error" );
  1218. pWO->bSelfDestruct = true;
  1219. return false;
  1220. }
  1221. const char* szKey;
  1222. if( *cgi.szPassword )
  1223. szKey = cgi.szPassword;
  1224. else
  1225. szKey = NULL;
  1226. if( pWO->ChannelCreate( szNewChannelName, szKey, true, cgi.iPlayerMax, cgi.bTournament, pWO->iLobbyLast, cgi.GameKind ) )
  1227. pWO->OnEnteringGameChannel( szNewChannelName, true, cgi );
  1228. else
  1229. {
  1230. pWO->OnFailedToEnterGameChannel();
  1231. // debugprint( "CreateGameChannel fail" );
  1232. return false;
  1233. }
  1234. *pWO->szChannelReturnOnGameEnterFail = 0;
  1235. return true;
  1236. }
  1237. //***********************************************************************************************
  1238. bool ProcessChannelListSelection( WolapiObject* pWO, IconListClass& chatlist, IconListClass& chanlist, int iIndex )
  1239. {
  1240. // Takes whatever action necessary due to user selecting iIndex from chanlist.
  1241. // Returns true if user selected to enter a game channel, else false.
  1242. if( iIndex < 0 )
  1243. return false;
  1244. // debugprint( "iIndex %i\n", iIndex );
  1245. const char* szChannelType = chanlist.Get_Item_ExtraDataString( iIndex );
  1246. if( szChannelType )
  1247. {
  1248. //debugprint( "szChannelType %s\n", szChannelType );
  1249. if( strcmp( szChannelType, CHANNELTYPE_OFFICIALCHAT ) == 0 )
  1250. {
  1251. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1252. {
  1253. if( !ExitChatChannel( pWO ) )
  1254. {
  1255. pWO->bSelfDestruct = true;
  1256. return false;
  1257. }
  1258. }
  1259. pWO->EnterLevel_OfficialChat();
  1260. }
  1261. else if( strcmp( szChannelType, CHANNELTYPE_USERCHAT ) == 0 )
  1262. {
  1263. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1264. {
  1265. if( !ExitChatChannel( pWO ) )
  1266. {
  1267. pWO->bSelfDestruct = true;
  1268. return false;
  1269. }
  1270. }
  1271. pWO->EnterLevel_UserChat();
  1272. }
  1273. else if( strcmp( szChannelType, CHANNELTYPE_TOP ) == 0 )
  1274. {
  1275. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1276. {
  1277. // Now not possible.
  1278. if( !ExitChatChannel( pWO ) )
  1279. {
  1280. pWO->bSelfDestruct = true;
  1281. return false;
  1282. }
  1283. }
  1284. pWO->EnterLevel_Top();
  1285. }
  1286. else if( strcmp( szChannelType, CHANNELTYPE_GAMES ) == 0 )
  1287. {
  1288. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1289. {
  1290. // Now not possible.
  1291. if( !ExitChatChannel( pWO ) )
  1292. {
  1293. pWO->bSelfDestruct = true;
  1294. return false;
  1295. }
  1296. }
  1297. pWO->EnterLevel_Games();
  1298. }
  1299. else if( strcmp( szChannelType, CHANNELTYPE_GAMESOFTYPE ) == 0 )
  1300. {
  1301. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1302. {
  1303. // Now not possible.
  1304. if( !ExitChatChannel( pWO ) )
  1305. {
  1306. pWO->bSelfDestruct = true;
  1307. return false;
  1308. }
  1309. }
  1310. void* pExtraData = chanlist.Get_Item_ExtraDataPtr( iIndex );
  1311. pWO->EnterLevel_GamesOfType( (WOL_GAMETYPEINFO*)pExtraData );
  1312. }
  1313. else if( strcmp( szChannelType, CHANNELTYPE_CHATCHANNEL ) == 0 )
  1314. {
  1315. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1316. {
  1317. // Not currently possible.
  1318. // debugprint( "Trying to jump from channel to channel?!\n" );
  1319. pWO->bSelfDestruct = true;
  1320. return false;
  1321. }
  1322. // Join the chat channel.
  1323. EnterChannel( pWO, chatlist, chanlist, iIndex, false ); // Can fail.
  1324. }
  1325. else if( strcmp( szChannelType, CHANNELTYPE_GAMECHANNEL ) == 0 )
  1326. {
  1327. // User attempting to join game channel.
  1328. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1329. {
  1330. // Not currently possible.
  1331. // debugprint( "Trying to jump from channel to channel?!\n" );
  1332. pWO->bSelfDestruct = true;
  1333. return false;
  1334. }
  1335. // Check if local user is allowed to join GameKind.
  1336. Channel* pChannel = (Channel*)chanlist.Get_Item_ExtraDataPtr( iIndex );
  1337. if( pChannel->type == GAME_TYPE )
  1338. {
  1339. // It is a game of our type, at least.
  1340. CREATEGAMEINFO::GAMEKIND GameKind = (CREATEGAMEINFO::GAMEKIND)( pChannel->reserved & 0xFF000000 );
  1341. switch( GameKind )
  1342. {
  1343. case CREATEGAMEINFO::RAGAME:
  1344. break;
  1345. case CREATEGAMEINFO::CSGAME:
  1346. if( !Is_Counterstrike_Installed() )
  1347. {
  1348. WOL_PrintMessage( chatlist, TXT_WOL_NEEDCOUNTERSTRIKE, WOLCOLORREMAP_LOCALMACHINEMESS );
  1349. Sound_Effect( WOLSOUND_ERROR );
  1350. return false;
  1351. }
  1352. break;
  1353. case CREATEGAMEINFO::AMGAME:
  1354. if( !Is_Aftermath_Installed() )
  1355. {
  1356. WOL_PrintMessage( chatlist, TXT_WOL_NEEDAFTERMATH, WOLCOLORREMAP_LOCALMACHINEMESS );
  1357. Sound_Effect( WOLSOUND_ERROR );
  1358. return false;
  1359. }
  1360. break;
  1361. default:
  1362. // debugprint( "Illegal value for GameKind channel reserved field: %s\n", (char*)pChannel->name );
  1363. Sound_Effect( WOLSOUND_ERROR );
  1364. return false;
  1365. }
  1366. // Join the game channel.
  1367. if( EnterChannel( pWO, chatlist, chanlist, iIndex, true ) )
  1368. {
  1369. // Exit the chat dialog, go to game dialog.
  1370. return true;
  1371. }
  1372. }
  1373. else
  1374. {
  1375. // User doubleclicked on a game that is of a different type.
  1376. // Offer to take them to a web page regarding the game type.
  1377. pWO->DoGameAdvertising( pChannel );
  1378. }
  1379. }
  1380. else if( strcmp( szChannelType, CHANNELTYPE_LOBBIES ) == 0 )
  1381. {
  1382. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL )
  1383. {
  1384. // Not currently possible.
  1385. // debugprint( "Chat channel to lobbies level?!\n" );
  1386. pWO->bSelfDestruct = true;
  1387. return false;
  1388. }
  1389. if( pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  1390. {
  1391. if( !ExitChatChannel( pWO ) )
  1392. {
  1393. pWO->bSelfDestruct = true;
  1394. return false;
  1395. }
  1396. }
  1397. pWO->EnterLevel_Lobbies();
  1398. }
  1399. else if( strcmp( szChannelType, CHANNELTYPE_LOBBYCHANNEL ) == 0 )
  1400. {
  1401. if( pWO->CurrentLevel == WOL_LEVEL_INCHATCHANNEL ||
  1402. pWO->CurrentLevel == WOL_LEVEL_INLOBBY )
  1403. {
  1404. // Not currently possible.
  1405. // debugprint( "Chat or lobby channel to lobby channel?!\n" );
  1406. pWO->bSelfDestruct = true;
  1407. return false;
  1408. }
  1409. // Join the lobby chat channel.
  1410. EnterChannel( pWO, chatlist, chanlist, iIndex, false ); // Can fail.
  1411. }
  1412. else if( strcmp( szChannelType, CHANNELTYPE_LOADING ) == 0 )
  1413. {
  1414. // User clicked on the channel list loading notification - do nothing.
  1415. }
  1416. else
  1417. {
  1418. // debugprint( "Item selected in channel list unidentifiable from extradata field\n" );
  1419. pWO->bSelfDestruct = true;
  1420. return false;
  1421. }
  1422. }
  1423. return false;
  1424. }
  1425. //***********************************************************************************************
  1426. bool bLinkInList( const LinkClass* pListHead, const LinkClass* pLinkToFind )
  1427. {
  1428. const LinkClass* pLink = pListHead;
  1429. while( pLink )
  1430. {
  1431. if( pLink == pLinkToFind )
  1432. return true;
  1433. pLink = pLink->Get_Next();
  1434. }
  1435. return false;
  1436. }
  1437. #endif