Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / connection.cpp
blob8163ac6cb279b91838284bc093d79c8a9b1c8632
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
25 //////////////
26 // Includes //
27 //////////////
28 #include "stdpch.h"
30 // Misc.
31 #include "nel/misc/i18n.h"
32 #include "nel/misc/path.h"
33 #include "nel/misc/time_nl.h"
34 #include "nel/misc/algo.h"
35 #include "nel/misc/system_utils.h"
36 // 3D Interface.
37 #include "nel/3d/u_driver.h"
38 #include "nel/3d/u_text_context.h"
39 #include "nel/3d/stereo_display.h"
40 // Game Share
41 //#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE
42 #include "game_share/gender.h"
43 #include "game_share/character_summary.h"
44 #include "game_share/roles.h"
45 #include "game_share/character_title.h"
46 #include "game_share/shard_names.h"
47 #include "game_share/utils.h"
48 #include "game_share/bg_downloader_msg.h"
50 // Std.
51 #include <vector>
52 // Client
53 #include "connection.h"
54 #include "nel/gui/action_handler.h"
55 #include "sound_manager.h"
56 #include "input.h"
57 #include "login.h"
58 #include "login_progress_post_thread.h"
60 #include "client_cfg.h"
61 #include "actions_client.h"
62 #include "user_entity.h"
63 #include "time_client.h"
64 #include "net_manager.h"
65 #include "string_manager_client.h"
66 #include "far_tp.h"
67 #include "movie_shooter.h"
69 // Interface part
70 #include "interface_v3/interface_manager.h"
71 #include "interface_v3/character_3d.h"
72 #include "nel/gui/ctrl_button.h"
73 #include "interface_v3/input_handler_manager.h"
74 #include "nel/gui/group_editbox.h"
75 #include "nel/gui/interface_expr.h"
76 #include "init_main_loop.h"
77 #include "continent_manager.h"
78 #include "interface_v3/group_quick_help.h"
79 #include "nel/gui/dbgroup_combo_box.h"
81 #include "r2/dmc/client_edition_module.h"
82 #include "r2/editor.h"
83 #include "game_share/scenario.h"
84 #include "session_browser_impl.h"
86 #include "bg_downloader_access.h"
87 #include "main_loop.h"
89 #include "misc.h"
92 ////////////////
93 // Namespaces //
94 ////////////////
95 using namespace NLMISC;
96 using namespace NL3D;
97 using namespace NLNET;
98 using namespace std;
99 using namespace RSMGR;
100 using namespace R2;
104 /////////////
105 // Externs //
106 /////////////
107 extern uint32 Version; // Client Version.
108 extern UDriver *Driver;
109 extern UTextContext *TextContext;
110 extern bool game_exit;
112 extern CSoundManager *SoundMngr;
114 extern bool serverReceivedReady;
115 extern CContinentManager ContinentMngr;
117 extern bool MovieShooterSaving;
118 extern void endMovieShooting();
119 extern void replayMovieShooting();
120 extern void saveMovieShooting();
121 extern void displaySpecialTextProgress(const char *text);
122 extern bool InitMouseWithCursor(bool hardware);
124 extern bool SetMousePosFirstTime;
126 /////////////
127 // Globals // initialization occurs in the function : connection
128 /////////////
129 bool userChar;
130 bool noUserChar;
131 bool ConnectInterf;
132 bool CreateInterf;
133 bool CharacterInterf;
134 TTime UniversalTime;
135 std::vector<CCharacterSummary> CharacterSummaries;
136 std::string UsedFSAddr;
137 std::string UserPrivileges;
138 uint8 ServerPeopleActive = 255;
139 uint8 ServerCareerActive = 255;
141 bool WaitServerAnswer;
142 bool CharNameValidArrived;
143 bool CharNameValid;
144 string CharNameValidDBLink;
145 uint8 PlayerSelectedSlot = 0;
146 string PlayerSelectedFileName;
147 TSessionId PlayerSelectedMainland= (TSessionId)0; // This is the mainland selected at the SELECT perso!!
148 std::string PlayerSelectedHomeShardName;
149 std::string PlayerSelectedHomeShardNameWithParenthesis;
150 extern std::string CurrentCookie;
152 std::string NewKeysCharNameWanted; // name of the character for which a new keyset must be created
153 std::string NewKeysCharNameValidated;
154 std::string GameKeySet = "keys.xml";
155 std::string RingEditorKeySet = "keys_r2ed.xml";
157 string ScenarioFileName;
158 sint LoginCharsel = -1;
160 std::string ImportCharacter;
162 static const char *KeySetVarName = "BuiltInKeySets";
164 #define GROUP_LIST_CHARACTER "ui:outgame:charsel_import:import_list"
165 #define GROUP_LIST_MAINLAND "ui:outgame:appear_mainland:mainland_list"
166 #define GROUP_LIST_KEYSET "ui:outgame:appear_keyset:keyset_list"
167 vector<CMainlandSummary> Mainlands;
168 TSessionId MainlandSelected = (TSessionId)0; // This is the mainland selected at the CREATE perso!!
170 // This is the home session (mainland) of the selected character
171 TSessionId CharacterHomeSessionId = (TSessionId)0;
174 bool PatchBegun = false;
176 // \todo GUIGUI : USE TRANSPORT CLASS.
177 // SVersionAnswer versionAnswer;
180 // Finite State Machine : all the states before entering the game
181 // ------------------------------------------------------------------------------------------------
182 TInterfaceState globalMenu();
185 bool hasPrivilegeDEV() { return (UserPrivileges.find(":DEV:") != std::string::npos); }
186 bool hasPrivilegeSGM() { return (UserPrivileges.find(":SGM:") != std::string::npos); }
187 bool hasPrivilegeGM() { return (UserPrivileges.find(":GM:") != std::string::npos); }
188 bool hasPrivilegeVG() { return (UserPrivileges.find(":VG:") != std::string::npos); }
189 bool hasPrivilegeSG() { return (UserPrivileges.find(":SG:") != std::string::npos); }
190 bool hasPrivilegeG() { return (UserPrivileges.find(":G:") != std::string::npos); }
191 bool hasPrivilegeEM() { return (UserPrivileges.find(":EM:") != std::string::npos); }
192 bool hasPrivilegeEG() { return (UserPrivileges.find(":EG:") != std::string::npos); }
195 // Restore the video mode (fullscreen for example) after the connection (done in a window)
196 void connectionRestoreVideoMode ()
198 if (StereoDisplay)
199 StereoDisplayAttached = StereoDisplay->attachToDisplay();
201 // And setup hardware mouse if we have to
202 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached);
203 SetMouseFreeLook ();
204 SetMouseCursor ();
205 SetMouseSpeed (ClientCfg.CursorSpeed);
206 SetMouseAcceleration (ClientCfg.CursorAcceleration);
208 // Restore user UI scaling
209 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
213 #define UI_VARIABLES_SCREEN_WEBSTART 8
216 // ***************************************************************************
217 // Called to reload the start test page in test browser mode
218 class CAHOnReloadTestPage: public IActionHandler
220 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
222 CInterfaceManager *pIM = CInterfaceManager::getInstance();
223 // need to reset password and current screen
224 CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
226 pGH->browse(ClientCfg.TestBrowserUrl.c_str());
230 REGISTER_ACTION_HANDLER (CAHOnReloadTestPage, "on_reload_test_page");
233 // ------------------------------------------------------------------------------------------------
234 void setOutGameFullScreen()
236 if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1)
238 if (StereoDisplayAttached)
239 StereoDisplay->detachFromDisplay();
240 StereoDisplayAttached = false;
242 InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached);
245 // Enable auto scaling in login window
246 CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
249 // ------------------------------------------------------------------------------------------------
250 class CSoundGlobalMenu
252 public:
253 CSoundGlobalMenu()
255 _MusicWantedAsync= false;
256 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
258 void reset();
259 void setMusic(const string &music, bool async);
260 void updateSound();
261 private:
262 string _MusicPlayed;
263 string _MusicWanted;
264 bool _MusicWantedAsync;
265 sint _NbFrameBeforeChange;
266 enum {NbFrameBeforeChangeMax= 10};
269 void CSoundGlobalMenu::reset()
271 _MusicPlayed.clear();
272 _MusicWanted.clear();
275 void CSoundGlobalMenu::updateSound()
277 // **** update the music played
278 // The first music played is the music played at loading, before select char
279 if (_MusicPlayed.empty())
280 _MusicPlayed = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
281 if (_MusicWanted.empty())
282 _MusicWanted = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
284 // because music is changed when the player select other race for instance,
285 // wait the 3D to load (stall some secs)
287 // if the wanted music is the same as the one currently playing, just continue playing
288 if(_MusicPlayed!=_MusicWanted)
290 // wait nbFrameBeforeChangeMax before actually changing the music
291 _NbFrameBeforeChange--;
292 if(_NbFrameBeforeChange<=0)
294 _MusicPlayed= _MusicWanted;
295 // play the music
296 if (SoundMngr != NULL)
297 SoundMngr->playMusic(_MusicPlayed, 500, _MusicWantedAsync, true, true);
302 // **** update mngr
303 if (SoundMngr != NULL)
304 SoundMngr->update();
307 void CSoundGlobalMenu::setMusic(const string &music, bool async)
309 _MusicWanted= toLowerAscii(music);
310 _MusicWantedAsync= async;
311 // reset the counter
312 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
314 static CSoundGlobalMenu SoundGlobalMenu;
317 // New version of the menu after the server connection
319 // If you add something in this function, check CFarTP,
320 // some kind of reinitialization might be useful over there.
321 // ------------------------------------------------------------------------------------------------
322 bool connection (const string &cookie, const string &fsaddr)
325 NLMISC::TTime connStart = ryzomGetLocalTime();
326 NLMISC::TTime connLast = connStart;
327 NLMISC::TTime connCurrent = connLast;
329 game_exit = false;
331 // set resolution from cfg after login
332 connectionRestoreVideoMode ();
334 // Preload continents
336 const string nmsg("Loading continents...");
337 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
338 ContinentMngr.preloadSheets();
340 connLast = connCurrent;
341 connCurrent = ryzomGetLocalTime();
342 nlinfo ("PROFILE: %d seconds (%d total) for Loading continents", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
345 if (!fsaddr.empty () && !cookie.empty ())
347 // it means that we have a nel_launcher values, so we are online
348 ClientCfg.Local = 0;
349 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
352 CInterfaceManager *pIM = CInterfaceManager::getInstance();
354 // If the Client is in in Local Mode -> init the Time and return.
355 if (ClientCfg.Local)
357 #ifdef ENABLE_INCOMING_MSG_RECORDER
358 NetMngr.init("", "");
359 // Set the impulse callback.
360 NetMngr.setImpulseCallback (impulseCallBack);
361 // Set the database.
362 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
363 // init the string manager cache.
364 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
365 #endif
366 return true;
369 ProgressBar.setFontFactor(1.0f);
371 // Init out game
372 setOutGameFullScreen();
374 string nmsg("Initializing outgame...");
375 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
376 pIM->initOutGame();
378 connLast = connCurrent;
379 connCurrent = ryzomGetLocalTime();
380 nlinfo ("PROFILE: %d seconds (%d total) for Initializing outgame", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
382 // Init user interface
383 nmsg = "Initializing user interface...";
384 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
386 // Hide cursor for interface
387 //Driver->showCursor (false);
389 // Init global variables
390 userChar = false;
391 noUserChar = false;
392 ConnectInterf = true;
393 CreateInterf = true;
394 CharacterInterf = true;
395 WaitServerAnswer= false;
397 FarTP.setOutgame();
399 // Start the finite state machine
400 static bool firstConnection = true;
401 TInterfaceState InterfaceState = AUTO_LOGIN;
402 // TInterfaceState InterfaceState = firstConnection ? AUTO_LOGIN : GLOBAL_MENU;
403 /*if (!firstConnection)
405 noUserChar = userChar = false;
406 WaitServerAnswer = true;
409 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(ClientCfg.Local ? 6 : -1); // TMP TMP
410 IngameDbMngr.flushObserverCalls();
411 NLGUI::CDBManager::getInstance()->flushObserverCalls();
413 // Active inputs
414 Actions.enable(true);
415 EditActions.enable(true);
417 if (ClientCfg.SelectCharacter == -1)
419 // not initialized at login and remain hardware until here ...
421 // Re-initialise the mouse (will be now in hardware mode, if required)
422 //InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
424 // no ui init if character selection is automatic
425 //SetMouseFreeLook ();
426 //SetMouseCursor ();
427 SetMouseSpeed (ClientCfg.CursorSpeed);
428 SetMouseAcceleration (ClientCfg.CursorAcceleration);
430 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
431 PlayerSelectedSlot = ClientCfg.SelectedSlot;
434 connLast = connCurrent;
435 connCurrent = ryzomGetLocalTime();
436 nlinfo ("PROFILE: %d seconds (%d total) for Initializing user interface", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
438 nlinfo ("PROFILE: %d seconds for connection", (uint32)(ryzomGetLocalTime ()-connStart)/1000);
440 // Init web box
442 // TMP TMP
443 if (ClientCfg.Local)
445 InterfaceState = GLOBAL_MENU;
448 // No loading music here, this is right before character selection, using the existing music
450 // Create the loading texture. We can't do that before because we need to add search path first.
451 beginLoading (LoadBackground);
452 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
454 while ((InterfaceState != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
456 switch (InterfaceState)
458 case AUTO_LOGIN:
459 InterfaceState = autoLogin (cookie, fsaddr, firstConnection);
460 break;
462 case GLOBAL_MENU:
463 if (!ClientCfg.Local)
465 if (ClientCfg.SelectCharacter == -1)
467 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
470 InterfaceState = globalMenu();
471 break;
472 case GOGOGO_IN_THE_GAME:
473 break;
474 case QUIT_THE_GAME:
475 break;
479 firstConnection = false;
481 // Restore user UI scaling
482 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
484 // Disable inputs
485 Actions.enable(false);
486 EditActions.enable(false);
488 // resetTextContext ("ingame.ttf", true);
489 resetTextContext ("ryzom.ttf", true);
491 if (InterfaceState == GOGOGO_IN_THE_GAME)
493 // set background downloader to 'paused' to ease loading of client
494 #ifdef RYZOM_BG_DOWNLOADER
495 pauseBGDownloader();
496 #endif
497 return true;
500 if (InterfaceState == QUIT_THE_GAME)
501 return false;
502 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
503 return true;
509 // Allow user to reselect character after the server reconnection
510 // ------------------------------------------------------------------------------------------------
511 bool reconnection()
514 game_exit = false;
516 setOutGameFullScreen();
518 // Preload continents
520 const string nmsg ("Loading continents...");
521 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
522 ContinentMngr.preloadSheets();
525 if (!fsaddr.empty () && !cookie.empty ())
527 // it means that we have a nel_launcher values, so we are online
528 ClientCfg.Local = 0;
529 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
532 // If the Client is in in Local Mode -> init the Time and return.
533 if (ClientCfg.Local)
535 #ifdef ENABLE_INCOMING_MSG_RECORDER
536 NetMngr.init("", "");
537 // Set the impulse callback.
538 NetMngr.setImpulseCallback (impulseCallBack);
539 // Set the database.
540 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
541 // init the string manager cache.
542 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
543 #endif
544 connectionRestoreVideoMode ();
545 return true;
549 CInterfaceManager *pIM = CInterfaceManager::getInstance();
551 ProgressBar.setFontFactor(1.0f);
553 // Init out game
554 SoundGlobalMenu.reset();
555 pIM->initOutGame();
557 // Hide cursor for interface
558 Driver->showCursor (false);
560 // Init global variables
561 userChar = false;
562 noUserChar = false;
563 ConnectInterf = true;
564 CreateInterf = true;
565 CharacterInterf = true;
566 WaitServerAnswer= false;
568 FarTP.setOutgame();
570 if (SoundMngr)
571 SoundMngr->setupFadeSound(1.0f, 1.0f);
573 // these two globals sequence GlobalMenu to display the character select dialog
574 WaitServerAnswer = true;
575 userChar = true;
577 // Start the finite state machine
578 TInterfaceState InterfaceState = GLOBAL_MENU;
580 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(-1);
581 IngameDbMngr.flushObserverCalls();
582 NLGUI::CDBManager::getInstance()->flushObserverCalls();
584 // Active inputs
585 Actions.enable(true);
586 EditActions.enable(true);
588 if (ClientCfg.SelectCharacter == -1)
590 // Re-initialise the mouse (will be now in hardware mode, if required)
591 SetMousePosFirstTime = true;
592 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
594 // no ui init if character selection is automatic
595 SetMouseFreeLook ();
596 SetMouseCursor ();
597 SetMouseSpeed (ClientCfg.CursorSpeed);
598 SetMouseAcceleration (ClientCfg.CursorAcceleration);
599 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
600 PlayerSelectedSlot = ClientCfg.SelectedSlot;
603 // we want the teleport graphics to display (not like in Server Hop mode)
604 // this also kicks the state machine to sendReady() so we stop spinning in farTPmainLoop
605 FarTP.setIngame();
607 // Not loading music here, this is before character selection, keep existing music
609 // Create the loading texture. We can't do that before because we need to add search path first.
610 beginLoading (LoadBackground);
611 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
613 // character selection menu
614 while( InterfaceState == GLOBAL_MENU ) // != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
616 if (ClientCfg.SelectCharacter == -1)
618 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
620 InterfaceState = globalMenu();
623 // Restore user UI scaling
624 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
626 // Disable inputs
627 Actions.enable(false);
628 EditActions.enable(false);
630 // resetTextContext ("ingame.ttf", true);
631 resetTextContext ("ryzom.ttf", true);
633 if (InterfaceState == GOGOGO_IN_THE_GAME)
635 #ifdef RYZOM_BG_DOWNLOADER
636 pauseBGDownloader();
637 #endif
638 return true;
640 if (InterfaceState == QUIT_THE_GAME)
641 return false;
642 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
643 return true;
646 // Automatic connection to the server, the user can't do anything
647 // ------------------------------------------------------------------------------------------------
648 TInterfaceState autoLogin (const string &cookie, const string &fsaddr, bool firstConnection)
650 noUserChar = userChar = false;
651 string defaultPort = string(":47851");
652 if(!fsaddr.empty())
654 // If we have a front end address from command line, use this one
655 UsedFSAddr = fsaddr;
656 if (UsedFSAddr.find(":") == string::npos)
658 UsedFSAddr += defaultPort;
661 else
663 // Otherwise, use the front end address from configfile
664 UsedFSAddr = ClientCfg.FSHost;
665 FSAddr = UsedFSAddr; // to be able to do /reconnect
666 LoginSM.pushEvent( CLoginStateMachine::ev_skip_all_login );
667 if (UsedFSAddr.find(":") == string::npos)
669 UsedFSAddr += defaultPort;
670 FSAddr += defaultPort; // to be able to do /reconnect
674 if (firstConnection)
675 NetMngr.init (cookie, UsedFSAddr);
677 // Connection
678 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
680 string result;
682 if (firstConnection)
684 NetMngr.connect (result);
686 if (!result.empty())
688 nlerror ("connection : %s.", result.c_str());
689 return QUIT_THE_GAME;
692 // Ok the client is connected
694 // Set the impulse callback.
695 NetMngr.setImpulseCallback (impulseCallBack);
696 // Set the database.
697 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
699 // init the string manager cache.
700 STRING_MANAGER::CStringManagerClient::instance()->initCache(UsedFSAddr, ClientCfg.LanguageCode);
703 else
705 CCharacterSummary cs;
706 cs.Name = "babar";
707 //cs.Surname = "l'elephant";
708 cs.People = EGSPD::CPeople::Zorai;
709 cs.VisualPropA.PropertySubData.Sex = 0; // Male
710 //Deprecated
711 // cs.Role = ROLES::range_warrior;
712 // cs.Job = JOBS::CasterBuffer;
713 // cs.JobLevel = 16;
714 CharacterSummaries.push_back(cs);
716 cs.Name = "yeah";
717 //cs.Surname = "zeelot";
718 cs.People = EGSPD::CPeople::Matis;
719 cs.VisualPropA.PropertySubData.Sex = 1; // Female
720 //Deprecated
721 // cs.Role = ROLES::buffer_magician;
722 // cs.Job = JOBS::CasterHealer;
723 // cs.JobLevel = 8;
724 CharacterSummaries.push_back(cs);
726 userChar = true;
729 WaitServerAnswer = true;
731 return GLOBAL_MENU;
734 // ------------------------------------------------------------------------------------------------
735 void globalMenuMovieShooter()
738 if(MovieShooterSaving)
740 // Add the buffer frame to the movie.
741 if(!MovieShooter.addFrame(TimeInSec, Driver))
743 // Fail to add the frame => abort.
744 endMovieShooting();
746 else
748 // Ok, just add a display.
749 displaySpecialTextProgress("MovieShooting");
755 // ------------------------------------------------------------------------------------------------
756 // Build a valid PlayerName for file Save selection.
757 std::string buildPlayerNameForSaveFile(const std::string &playerNameIn)
759 // remove any shard name appended
760 string playerName = playerNameIn;
761 string::size_type pos = playerNameIn.find('(');
762 if(pos!=string::npos && pos>0)
764 playerName.resize(pos);
767 // replace any special ucchar with '_'
768 string ret;
769 ret.resize(playerName.size());
770 for(uint i=0;i<playerName.size();i++)
772 ucchar c= playerName[i];
773 if( (c>='A' && c<='Z') ||
774 (c>='a' && c<='z') ||
775 (c>='0' && c<='9') ||
776 (c=='_') )
778 ret[i]= tolower(c); // TODO: toLowerAscii
780 else
781 ret[i]= '_';
783 return ret;
787 #ifdef RYZOM_BG_DOWNLOADER
788 static bool LuaBGDSuccessFlag = true; // tmp, for debug
790 void updateBGDownloaderUI()
792 CInterfaceManager *im = CInterfaceManager::getInstance();
793 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
794 bool bgWindowVisible = true;
795 if (im->isInGame())
797 static NLMISC::CRefPtr<CInterfaceElement> bgDownloaderWindow;
798 if (!bgDownloaderWindow)
800 bgDownloaderWindow = CWidgetManager::getInstance()->getElementFromId("ui:interface:bg_downloader");
802 bgWindowVisible = bgDownloaderWindow && bgDownloaderWindow->getActive();
804 bool prevSuccess = LuaBGDSuccessFlag;
805 if (isBGDownloadEnabled() && PatchBegun)
807 if (AvailablePatchs == 0)
809 if (LuaBGDSuccessFlag)
811 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
814 else
816 switch(bgDownloader.getLastTaskResult())
818 case BGDownloader::TaskResult_Unknown:
820 float progress = 0.f;
821 /*if (bgDownloader.getTotalSize() != 0)
823 progress = (float) bgDownloader.getPatchingSize() / bgDownloader.getTotalSize();
825 if (bgDownloader.getTotalFilesToGet() != 0)
827 progress = (bgDownloader.getCurrentFilesToGet() + bgDownloader.getCurrentFileProgress()) / bgDownloader.getTotalFilesToGet();
829 if (LuaBGDSuccessFlag && bgWindowVisible)
831 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript(toString("bgdownloader:setPatchProgress(%f)", progress));
833 // display current priority of the downloader
834 if (LuaBGDSuccessFlag && bgWindowVisible)
836 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:displayPriority()");
839 break;
840 case BGDownloader::TaskResult_Success:
841 if (LuaBGDSuccessFlag && bgWindowVisible)
843 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
845 // task finished
846 AvailablePatchs = 0;
847 if (bgDownloader.getPatchCompletionFlag(true /* clear flag */))
849 // when in-game, display a message to signal the end of the patch
850 if (im->isInGame())
852 im->displaySystemInfo(CI18N::get("uiBGD_InGamePatchCompletion"), "BC");
855 break;
856 default:
857 // error case
858 if (LuaBGDSuccessFlag && bgWindowVisible)
860 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchError()");
862 break;
866 else
868 if (LuaBGDSuccessFlag && bgWindowVisible)
870 if (isBGDownloadEnabled())
872 // no necessary patch for now
873 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoNecessaryPatch()");
875 else
877 // no download ui
878 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoDownloader()");
882 if (prevSuccess != LuaBGDSuccessFlag)
884 nlwarning("Some scipt error occurred");
887 #endif
889 // compute patcher priority, depending on the presence of one or more mainland characters : in this case, give the patch a boost
890 void updatePatcherPriorityBasedOnCharacters()
892 #ifdef RYZOM_BG_DOWNLOADER
893 if (isBGDownloadEnabled())
895 if (CBGDownloaderAccess::getInstance().getDownloadThreadPriority() != BGDownloader::ThreadPriority_Paused)
897 // choose priority based on available characters :
898 bool hasMainlandChar = false;
899 for(std::vector<CCharacterSummary>::iterator it = CharacterSummaries.begin(); it != CharacterSummaries.end(); ++it)
901 if (it->Name.empty()) continue;
902 if (!it->InNewbieland)
904 hasMainlandChar = true;
905 break;
908 CBGDownloaderAccess::getInstance().requestDownloadThreadPriority(hasMainlandChar ? BGDownloader::ThreadPriority_Normal : BGDownloader::ThreadPriority_Low, false);
911 #endif
914 // Launch the interface to choose a character
915 // ------------------------------------------------------------------------------------------------
916 TInterfaceState globalMenu()
918 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_CharacterSelection, "login_step_character_selection"));
920 #ifdef RYZOM_BG_DOWNLOADER
921 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
923 if (isBGDownloadEnabled())
925 // If there's a need for mainland download, then proceed
926 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
928 // if a task is already started, then this was a situation where player went back from game to the character selection,
929 // so just unpause
930 BGDownloader::TTaskResult dummyResult;
931 ucstring dummyMessage; // OLD
932 if (!bgDownloader.isTaskEnded(dummyResult, dummyMessage))
934 unpauseBGDownloader();
938 #endif
940 CInterfaceManager *pIM = CInterfaceManager::getInstance();
942 sint32 nScreenConnecting, nScreenIntro, nScreenServerCrashed;
943 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_connecting"), nScreenConnecting);
944 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_intro"), nScreenIntro);
945 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_crashing"), nScreenServerCrashed);
947 // SKIP INTRO : Write to the database if we have to skip the intro and write we want to skip further intro to client cfg
948 if (ClientCfg.SkipIntro)
950 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:SKIP_INTRO", false);
951 if (pNL != NULL)
952 pNL->setValue64(1);
955 TGameCycle serverTick = NetMngr.getCurrentServerTick();
956 bool PlayerWantToGoInGame = false;
957 bool firewallTimeout = false;
959 ProgressBar.finish(); // no progress while selecting character
961 while (PlayerWantToGoInGame == false)
964 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
965 // tmp for debug
966 if (::GetAsyncKeyState(VK_SPACE))
968 pIM->uninitOutGame();
969 pIM->initOutGame();
970 CWidgetManager::getInstance()->activateMasterGroup ("ui:outgame", true);
971 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(2); // TMP TMP
972 IngameDbMngr.flushObserverCalls();
973 NLGUI::CDBManager::getInstance()->flushObserverCalls();
974 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(false);
975 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(true);
976 // Active inputs
977 Actions.enable(true);
978 EditActions.enable(true);
979 LuaBGDSuccessFlag = true;
980 CWidgetManager::getInstance()->getParser()->reloadAllLuaFileScripts();
982 #endif
984 #ifdef RYZOM_BG_DOWNLOADER
985 updateBGDownloaderUI();
986 #endif
988 // Update network.
991 if ( ! firewallTimeout )
992 NetMngr.update();
994 catch (const EBlockedByFirewall&)
996 if ( NetMngr.getConnectionState() == CNetManager::Disconnect )
998 firewallTimeout = true;
1000 else
1002 // Display the firewall alert string
1003 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:connecting:title"));
1004 if (pVT != NULL)
1005 pVT->setTextLocalized("uiFirewallAlert", true);
1007 // The mouse and fullscreen mode should be unlocked for the user to set the firewall permission
1008 nlSleep( 30 ); // 'nice' the client, and prevent to make too many send attempts
1012 IngameDbMngr.flushObserverCalls();
1013 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1015 // check if we can send another dated block
1016 if (NetMngr.getCurrentServerTick() != serverTick)
1019 serverTick = NetMngr.getCurrentServerTick();
1020 NetMngr.send(serverTick);
1022 else
1024 // Send dummy info
1025 NetMngr.send();
1027 // Update the DT T0 and T1 global variables
1028 updateClientTime();
1029 CInputHandlerManager::getInstance()->pumpEvents();
1030 Driver->clearBuffers(CRGBA::Black);
1031 Driver->setMatrixMode2D11();
1033 // Update sound
1034 SoundGlobalMenu.updateSound();
1036 // Interface handling & displaying (processes clicks...)
1037 pIM->updateFrameEvents();
1038 pIM->updateFrameViews(NULL);
1039 IngameDbMngr.flushObserverCalls();
1040 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1042 // Movie shooter
1043 globalMenuMovieShooter();
1045 // Force the client to sleep a bit.
1046 if(ClientCfg.Sleep >= 0)
1048 nlSleep(ClientCfg.Sleep);
1051 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
1052 if (::GetAsyncKeyState(VK_CONTROL))
1054 pIM->displayUIViewBBoxs("");
1055 pIM->displayUICtrlBBoxs("");
1056 pIM->displayUIGroupBBoxs("");
1057 displayDebugUIUnderMouse();
1059 #endif
1061 // Display
1062 Driver->swapBuffers();
1064 // SERVER INTERACTIONS WITH INTERFACE
1065 if (WaitServerAnswer)
1067 if (noUserChar || userChar)
1069 #ifdef RYZOM_BG_DOWNLOADER
1070 if (isBGDownloadEnabled())
1072 // If there's a need for mainland download, then proceed
1073 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
1075 // if a task is already started, then this was a situation where player went back from game to the character selection,
1076 // so just unpause
1077 BGDownloader::TTaskResult dummyResult;
1078 ucstring dummyMessage; // OLD
1079 if (bgDownloader.isTaskEnded(dummyResult, dummyMessage))
1081 // launch mainland patch as a background task
1082 BGDownloader::CTaskDesc task(BGDownloader::DLState_GetAndApplyPatch,
1083 (1 << BGDownloader::DownloadID_MainLand));
1084 bgDownloader.startTask(task, getBGDownloaderCommandLine(), false /* showDownloader */);
1086 // choose priority based on available characters :
1087 updatePatcherPriorityBasedOnCharacters();
1089 PatchBegun = true;
1093 #endif
1095 //nlinfo("impulseCallBack : received userChars list");
1096 noUserChar = userChar = false;
1097 if( FarTP.isReselectingChar() || !FarTP.isServerHopInProgress() ) // if doing a Server Hop, expect serverReceivedReady without action from the user
1099 sint charSelect = -1;
1100 if (ClientCfg.SelectCharacter != -1)
1101 charSelect = ClientCfg.SelectCharacter;
1103 if (LoginCharsel != -1)
1104 charSelect = LoginCharsel;
1106 WaitServerAnswer = false;
1107 if (charSelect == -1)
1109 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_CHARS", false);
1110 if (pNL != NULL)
1112 pNL->setValue64 (1); // Send impulse to interface observers
1113 IngameDbMngr.flushObserverCalls();
1114 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1115 pNL->setValue64 (0);
1116 IngameDbMngr.flushObserverCalls();
1117 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1120 else
1122 // check that the pre selected character is available
1123 if (CharacterSummaries[charSelect].People == EGSPD::CPeople::Unknown || charSelect > 4)
1125 // BAD ! preselected char does not exist, use the first available or fail
1126 uint i;
1127 for (i=0; i<CharacterSummaries.size(); ++i)
1129 if (CharacterSummaries[i].People != EGSPD::CPeople::Unknown)
1130 break;
1132 if (i == CharacterSummaries.size())
1134 Driver->systemMessageBox("You have no character for the current user.\nClient will exit.", "Char loading error", UDriver::okType, UDriver::exclamationIcon);
1135 exit(-1);
1137 else
1139 UDriver::TMessageBoxId ret = Driver->systemMessageBox("The pre-selected character doesn't exist.\nDo you want to use the first available character instead ?", "Char loading error", UDriver::yesNoType, UDriver::warningIcon);
1140 if (ret == UDriver::noId)
1141 exit(-1);
1142 else
1143 charSelect = i;
1146 // Auto-selection for fast launching (dev only)
1147 CAHManager::getInstance()->runActionHandler("launch_game", NULL, toString("slot=%d|edit_mode=0", charSelect));
1149 if (LoginCharsel == -1)
1150 ClientCfg.SelectCharacter = charSelect;
1155 // Clear sending buffer that may contain prevous QUIT_GAME when getting back to the char selection screen
1156 NetMngr.flushSendBuffer();
1159 if (CharNameValidArrived)
1161 //nlinfo("impulseCallBack : received CharNameValidArrived");
1162 CharNameValidArrived = false;
1163 WaitServerAnswer = false;
1164 if (ClientCfg.SelectCharacter == -1)
1166 CCDBNodeLeaf *pNL;
1167 pNL = NLGUI::CDBManager::getInstance()->getDbProp(CharNameValidDBLink,false);
1168 if (pNL != NULL)
1170 if (CharNameValid)
1171 pNL->setValue64(1);
1172 else
1173 pNL->setValue64(0);
1176 pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_VALID", false);
1177 if (pNL != NULL)
1179 pNL->setValue64 (1); // Send impulse to interface observers
1180 IngameDbMngr.flushObserverCalls();
1181 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1182 pNL->setValue64 (0);
1183 IngameDbMngr.flushObserverCalls();
1184 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1189 if (serverReceivedReady)
1191 //nlinfo("impulseCallBack : received serverReceivedReady");
1192 serverReceivedReady = false;
1193 WaitServerAnswer = false;
1194 PlayerWantToGoInGame = true;
1197 else
1199 noUserChar = false;
1200 userChar = false;
1201 CharNameValidArrived = false;
1202 serverReceivedReady = false;
1205 // Check if server disconnect the client
1206 if (!ClientCfg.Local)
1208 if (NetMngr.getConnectionState() == CNetManager::Disconnect)
1210 // Display the connection failure screen
1211 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:CURRENT_SCREEN", false);
1212 if (pNL != NULL)
1213 pNL->setValue64 (nScreenServerCrashed);
1215 if ( firewallTimeout )
1217 // Display the firewall error string instead of the normal failure string
1218 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:crashing:title"));
1219 if (pVT != NULL)
1221 pVT->setMultiLine( true );
1222 pVT->setTextLocalized(CI18N::get("uiFirewallFail")+".\n"+
1223 CI18N::get("uiFirewallAlert")+".", false);
1231 // We want to quit the game without playing
1232 if (game_exit)
1233 return QUIT_THE_GAME;
1236 if (ClientCfg.SelectCharacter != -1)
1237 PlayerSelectedSlot = ClientCfg.SelectCharacter;
1239 // Notify the state machine that we're exiting from global menu
1240 LoginSM.pushEvent(CLoginStateMachine::ev_global_menu_exited);
1242 // Init the current Player Name (for interface.cfg and sentence.name save). Make a good File Name.
1243 string playerName = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1244 PlayerSelectedFileName = buildPlayerNameForSaveFile(playerName);
1246 // Init the current Player Home shard Id and name
1247 CharacterHomeSessionId = CharacterSummaries[PlayerSelectedSlot].Mainland;
1248 PlayerSelectedMainland= CharacterSummaries[PlayerSelectedSlot].Mainland;
1249 PlayerSelectedHomeShardName.clear();
1250 PlayerSelectedHomeShardNameWithParenthesis.clear();
1251 for(uint i=0;i<CShardNames::getInstance().getSessionNames().size();i++)
1253 const CShardNames::TSessionName &sessionName= CShardNames::getInstance().getSessionNames()[i];
1254 if(PlayerSelectedMainland == sessionName.SessionId)
1256 PlayerSelectedHomeShardName= sessionName.DisplayName;
1257 PlayerSelectedHomeShardNameWithParenthesis= '(' + PlayerSelectedHomeShardName + ')';
1262 // Restore video mode
1263 if (ClientCfg.SelectCharacter == -1)
1264 connectionRestoreVideoMode ();
1266 // Skip intro next time
1267 ClientCfg.writeBool("SkipIntro", true);
1269 // return SELECT_CHARACTER;
1270 return GOGOGO_IN_THE_GAME;
1274 // Init the character selection slot texts from the character summaries
1275 // ------------------------------------------------------------------------------------------------
1276 class CAHNetInitCharSel : public IActionHandler
1278 public:
1279 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1281 string sPath = getParam(Params, "slottexts");
1282 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1283 uint i;
1284 for (i = 0; i < CharacterSummaries.size(); ++i)
1286 CCharacterSummary &rCS = CharacterSummaries[i];
1287 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i));
1288 CViewText *pVT = dynamic_cast<CViewText*>(pIE);
1289 if (pVT == NULL) return;
1291 if (rCS.Name.empty())
1292 pVT->setTextLocalized("uiEmptySlot", true);
1293 else
1294 pVT->setTextLocalized(rCS.Name.toUtf8(), false);
1296 // 5 slots
1297 for (; i < 5; ++i)
1299 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i)));
1300 if (pVT == NULL) return;
1301 pVT->setTextLocalized("uiEmptySlot", true);
1305 REGISTER_ACTION_HANDLER (CAHNetInitCharSel, "net_init_char_sel");
1307 // ------------------------------------------------------------------------------------------------
1308 void setTarget(CCtrlBase *ctrl, const string &targetName, std::string &value)
1310 std::vector<CInterfaceLink::CTargetInfo> targets;
1311 // find first enclosing group
1312 CCtrlBase *currCtrl = ctrl;
1313 CInterfaceGroup *ig = NULL;
1314 while (currCtrl)
1316 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1317 if (ig != NULL) break;
1318 currCtrl = currCtrl->getParent();
1320 if (ig)
1322 CInterfaceExprValue exprValue;
1323 exprValue.setString(value);
1325 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1326 for(uint k = 0; k < targets.size(); ++k)
1328 if (targets[k].Elem) targets[k].affect(exprValue);
1333 // ------------------------------------------------------------------------------------------------
1334 void setTarget(CCtrlBase *ctrl, const string &targetName, uint32 value)
1336 std::vector<CInterfaceLink::CTargetInfo> targets;
1337 // find first enclosing group
1338 CCtrlBase *currCtrl = ctrl;
1339 CInterfaceGroup *ig = NULL;
1340 while (currCtrl)
1342 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1343 if (ig != NULL) break;
1344 currCtrl = currCtrl->getParent();
1346 if (ig)
1348 CInterfaceExprValue exprValue;
1349 exprValue.setInteger(value);
1351 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1352 for(uint k = 0; k < targets.size(); ++k)
1354 if (targets[k].Elem) targets[k].affect(exprValue);
1359 // ------------------------------------------------------------------------------------------------
1360 class CAHGetSlot: public IActionHandler
1362 public:
1363 virtual void execute (CCtrlBase *pCaller, const string &Params)
1365 string sProp = getParam(Params, "prop");
1366 string sTarget = getParam(Params, "target");
1367 string sSlot = getParam(Params, "slot");
1369 CInterfaceExprValue result;
1370 if (!CInterfaceExpr::eval(sSlot, result))
1371 return;
1372 uint8 selectedSlot = (uint8)result.getInteger();
1373 if (selectedSlot >= CharacterSummaries.size())
1374 return;
1376 PlayerSelectedSlot = selectedSlot;
1378 if (CharacterSummaries[PlayerSelectedSlot].Name.empty())
1379 return;
1381 string sValue;
1382 uint32 nValue = 0;
1384 if (sProp == "name")
1386 sValue = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1387 setTarget (pCaller, sTarget, sValue);
1389 /* else if (sProp == "surname")
1390 Deprecated {
1391 sValue = CharacterSummaries[PlayerSelectedSlot].Surname;
1392 setTarget (pCaller, sTarget, sValue);
1394 */ else if (sProp == "title")
1396 bool womanTitle;
1397 if( CharacterSummaries[PlayerSelectedSlot].VisualPropA.PropertySubData.Sex == 1 )
1399 UserEntity->setGender( GSGENDER::female );
1400 womanTitle = true;
1402 else
1404 UserEntity->setGender( GSGENDER::male );
1405 womanTitle = false;
1407 string titleStr = CHARACTER_TITLE::toString(CharacterSummaries[PlayerSelectedSlot].Title);
1408 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(titleStr, womanTitle);
1410 // Sometimes translation contains another title
1411 string::size_type pos = sValue.find('$');
1412 if (pos != string::npos)
1414 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sValue), womanTitle);
1417 setTarget (pCaller, sTarget, sValue);
1419 /* else if (sProp == "orient")
1420 Deprecated {
1421 sValue = ROLES::roleToUCString(CharacterSummaries[PlayerSelectedSlot].Role);
1422 setTarget (pCaller, sTarget, sValue);
1424 else if (sProp == "job")
1426 //Deprecated
1427 // sValue = JOBS::jobToUCString(CharacterSummaries[PlayerSelectedSlot].Job);
1428 sValue = JOBS::jobToUCString(JOBS::BladeBearer);
1429 setTarget (pCaller, sTarget, sValue);
1431 */ else if (sProp == "level")
1433 //Deprecated
1434 // sValue = toString(CharacterSummaries[PlayerSelectedSlot].JobLevel);
1435 sValue = toString(1);
1436 setTarget (pCaller, sTarget, sValue);
1438 else if (sProp == "pos")
1440 nValue = CharacterSummaries[PlayerSelectedSlot].Location;
1441 setTarget (pCaller, sTarget, nValue);
1445 REGISTER_ACTION_HANDLER (CAHGetSlot, "get_slot");
1448 // Setup the database from a database entry which represents a slot
1449 // ------------------------------------------------------------------------------------------------
1450 class CAHSetDBFromSlot : public IActionHandler
1452 public:
1453 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1455 string sDBLink = getParam(Params, "dblink");
1456 string sSlot = getParam(Params, "slot");
1458 CInterfaceExprValue result;
1459 if (!CInterfaceExpr::eval(sSlot, result))
1460 return;
1462 PlayerSelectedSlot = (uint8)result.getInteger();
1464 if (PlayerSelectedSlot >= CharacterSummaries.size())
1465 return;
1467 // Setup the database from the character summary
1468 CCharacterSummary &rCS = CharacterSummaries[PlayerSelectedSlot];
1469 if (rCS.Name.empty())
1470 return;
1472 SCharacter3DSetup::setupDBFromCharacterSummary(sDBLink, rCS);
1475 REGISTER_ACTION_HANDLER (CAHSetDBFromSlot, "set_db_from_slot");
1478 // Reset all the pushed radio button of a group
1479 // ------------------------------------------------------------------------------------------------
1480 class CAHResetPushed: public IActionHandler
1482 public:
1483 virtual void execute (CCtrlBase *pCaller, const string &Params)
1485 string sDBLink = getParam(Params, "dblink");
1486 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1487 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(pCaller->getId(), sDBLink);
1488 CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup*>(pIE);
1489 if (pIG == NULL) return;
1491 const vector<CCtrlBase*> vCB = pIG->getControls();
1492 for (uint i = 0; i < vCB.size(); ++i)
1494 CCtrlBaseButton *pBut = dynamic_cast<CCtrlBaseButton*>(vCB[i]);
1495 if (pBut && pBut->getType() == CCtrlBaseButton::RadioButton)
1497 pBut->setPushed (false);
1502 REGISTER_ACTION_HANDLER (CAHResetPushed, "reset_pushed");
1508 // Launch the game given a slot (slot is reference to the character summaries
1509 // ------------------------------------------------------------------------------------------------
1510 class CAHLaunchGame : public IActionHandler
1512 public:
1513 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1515 // Get the edit/play mode
1516 string sEditMode = getParam(Params, "edit_mode");
1517 bool wantsEditMode = false;
1518 CInterfaceExprValue result;
1519 bool wantsNewScenario = false;
1521 if (CInterfaceExpr::eval(sEditMode, result))
1523 wantsEditMode = (result.getInteger() == 1) || (result.getInteger() == 2);
1524 wantsNewScenario = (result.getInteger() == 2);
1527 CInterfaceManager *im = CInterfaceManager::getInstance();
1528 if (wantsEditMode)
1530 // full patch needed for edition, warn the client
1531 if (AvailablePatchs != 0)
1533 if (im->isInGame())
1535 inGamePatchUncompleteWarning();
1537 else
1539 im->messageBoxWithHelp(CI18N::get("uiBGD_FullPatchNeeded"), "ui:outgame");
1541 return;
1545 // Get the player selected slot
1546 string sSlot = getParam(Params, "slot");
1547 if (sSlot != "ingame_auto")
1549 CInterfaceExprValue result;
1550 if (!CInterfaceExpr::eval(sSlot, result))
1551 return;
1552 PlayerSelectedSlot = (uint8)result.getInteger();
1553 if (PlayerSelectedSlot >= CharacterSummaries.size())
1554 return;
1556 ClientCfg.writeInt("SelectedSlot",PlayerSelectedSlot);
1557 if (ClientCfg.SaveConfig)
1558 ClientCfg.ConfigFile.save();
1563 static volatile bool isMainlandCharacter = false; // TMP until we can get this info
1564 if (isMainlandCharacter)
1566 nlassert(0); // use id="message_box" !!!
1567 if (AvailablePatchs != 0)
1569 im->messageBoxWithHelp(CI18N::get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame");
1571 return;
1576 // Select the right sheet to create the user character.
1577 ClientCfg.UserSheet = CharacterSummaries[PlayerSelectedSlot].SheetId.toString();
1579 // If the user wants to enter its editing session, get the ring server to Far TP to.
1580 if (wantsEditMode)
1583 if (wantsNewScenario)
1585 CSessionBrowserImpl &sb = CSessionBrowserImpl::getInstance();
1586 sb.init(NULL);
1587 sb.closeEditSession(sb.getCharId());
1588 sb.waitOneMessage(CSessionBrowserImpl::getMessageName("on_invokeResult"));
1590 if (FarTP.requestFarTPToSession( (TSessionId)0, PlayerSelectedSlot, CFarTP::LaunchEditor, false ))
1592 WaitServerAnswer = true; // prepare to receive the character messages
1595 // // If the player clicked 'Launch Editor', there was no CONNECTION:SELECT_CHAR sent yet,
1596 // // so don't wait for the EGS to acknowledge our quit message as he does not know our character
1597 // LoginSM.pushEvent(CLoginStateMachine::ev_ingame_return);
1599 return;
1602 // Send CONNECTION:SELECT_CHAR
1603 CBitMemStream out;
1604 nlverify( GenericMsgHeaderMngr.pushNameToStream ("CONNECTION:SELECT_CHAR", out) );
1605 //nlinfo("impulseCallBack : CONNECTION:SELECT_CHAR '%d' sent.", PlayerSelectedSlot);
1608 CSelectCharMsg SelectCharMsg;
1609 SelectCharMsg.c = (uint8)PlayerSelectedSlot;
1610 out.serial (SelectCharMsg);
1611 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1613 NetMngr.push(out);
1614 NetMngr.send(NetMngr.getCurrentServerTick());
1617 //PlayerWantToGoInGame = true;
1619 // CBitMemStream out2;
1620 // if(GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ENTER", out2))
1621 // {
1622 // NetMngr.push(out2);
1623 // nlinfo("impulseCallBack : CONNECTION:ENTER sent");
1624 // }
1625 // else
1626 // nlwarning("unknown message name : 'CONNECTION:ENTER'.");
1628 WaitServerAnswer = true;
1629 if (ClientCfg.Local)
1630 serverReceivedReady = true;
1633 REGISTER_ACTION_HANDLER (CAHLaunchGame, "launch_game");
1636 // Ask the server to create a character
1637 // ------------------------------------------------------------------------------------------------
1638 class CAHAskCreateChar : public IActionHandler
1640 public:
1641 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1643 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1645 // Create the message for the server to create the character.
1646 CBitMemStream out;
1647 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out))
1649 nlwarning ("don't know message name CONNECTION:CREATE_CHAR");
1650 return;
1653 // Setup the name
1654 string sEditBoxPath = getParam (Params, "name");
1655 string sFirstName = "NotSet";
1656 string sSurName = "NotSet";
1657 CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(sEditBoxPath));
1658 if (pGEB != NULL)
1659 sFirstName = pGEB->getInputString();
1660 else
1661 nlwarning ("can't get edit box name : %s",sEditBoxPath.c_str());
1663 // Build the character summary from the database branch ui:temp:char3d
1664 CCharacterSummary CS;
1665 string sCharSumPath = getParam(Params, "charsum");
1666 SCharacter3DSetup::setupCharacterSummaryFromDB(CS, sCharSumPath);
1667 CS.Mainland = MainlandSelected;
1668 CS.Name = ucstring::makeFromUtf8(sFirstName); // FIXME: UTF-8 (serial)
1669 //CS.Surname = sSurName;
1671 // Create the message to send to the server from the character summary
1672 CCreateCharMsg CreateCharMsg;
1674 CreateCharMsg.setupFromCharacterSummary(CS);
1676 // Slot
1678 string sSlot = getParam(Params, "slot");
1680 CInterfaceExprValue result;
1681 if (!CInterfaceExpr::eval(sSlot, result))
1682 return;
1684 CreateCharMsg.Slot = (uint8)result.getInteger();
1686 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(PlayerSelectedSlot);
1689 // Setup the new career
1690 string sCaracBasePath = getParam (Params, "caracs");
1691 CreateCharMsg.NbPointFighter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FIGHT")->getValue32();
1692 CreateCharMsg.NbPointCaster = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"MAGIC")->getValue32();
1693 CreateCharMsg.NbPointCrafter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"CRAFT")->getValue32();
1694 CreateCharMsg.NbPointHarvester = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FORAGE")->getValue32();
1696 // Setup starting point
1697 string sLocationPath = getParam(Params, "loc");
1699 CreateCharMsg.StartPoint = RYZOM_STARTING_POINT::borea;
1701 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp (sLocationPath, false);
1702 if (pNL != NULL)
1703 CreateCharMsg.StartPoint = (RYZOM_STARTING_POINT::TStartPoint)(pNL->getValue64());
1704 else
1705 nlwarning(("Can't read starting point from the database : " + sLocationPath).c_str());
1707 if (CS.People == EGSPD::CPeople::Fyros)
1708 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::fyros_start));
1709 else if (CS.People == EGSPD::CPeople::Matis)
1710 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::matis_start));
1711 else if (CS.People == EGSPD::CPeople::Tryker)
1712 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::tryker_start));
1713 else // if (CS.People == EGSPD::CPeople::Zorai)
1714 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::zorai_start));
1718 // Send the message to the server
1719 CreateCharMsg.serialBitMemStream (out);
1720 if (!ClientCfg.Local/*!ClientCfg.Light*/)
1722 noUserChar = userChar = false;
1724 NetMngr.push(out);
1725 NetMngr.send(NetMngr.getCurrentServerTick());
1727 //nlinfo("impulseCallBack : CONNECTION:CREATE_CHAR sent");
1728 CreateCharMsg.dump();
1730 else
1732 userChar = true;
1733 if (CharacterSummaries.size() < 5)
1734 CharacterSummaries.push_back(CS);
1736 WaitServerAnswer = true;
1739 REGISTER_ACTION_HANDLER (CAHAskCreateChar, "ask_create_char");
1743 // Ask the server to delete a character
1744 // ------------------------------------------------------------------------------------------------
1745 class CAHAskDeleteChar : public IActionHandler
1747 public:
1748 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1750 // Create the message for the server to create the character.
1751 CBitMemStream out;
1752 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:DELETE_CHAR", out))
1754 nlwarning ("don't know message name CONNECTION:DELETE_CHAR");
1755 return;
1758 // Get the selected slot
1759 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1761 string sSlot = getParam(Params, "slot");
1763 CInterfaceExprValue result;
1764 if (!CInterfaceExpr::eval(sSlot, result))
1765 return;
1767 uint8 nSelectedSlot = (uint8)result.getInteger();
1768 if (nSelectedSlot >= CharacterSummaries.size())
1769 return;
1771 out.serial (nSelectedSlot);
1773 // Yoyo: delete the Local files. To avoid problem if recreate a character with same name.
1774 string playerName = CharacterSummaries[nSelectedSlot].Name.toUtf8();
1775 string playerDeletedFileName = buildPlayerNameForSaveFile(playerName);
1776 // Delete the 2 Local files
1777 pIM->deletePlayerConfig(playerDeletedFileName);
1778 pIM->deletePlayerKeys(playerDeletedFileName);
1780 // Send the message to the server
1781 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1783 noUserChar = userChar = false;
1784 NetMngr.push(out);
1785 NetMngr.send(NetMngr.getCurrentServerTick());
1787 //nlinfo("impulseCallBack : CONNECTION:DELETE_CHAR %d sent", nSelectedSlot);
1789 else
1791 if (nSelectedSlot < CharacterSummaries.size())
1792 CharacterSummaries.erase (CharacterSummaries.begin()+nSelectedSlot);
1793 if (CharacterSummaries.size() != 0)
1794 userChar = true;
1795 else
1796 noUserChar = true;
1798 WaitServerAnswer = true;
1801 REGISTER_ACTION_HANDLER (CAHAskDeleteChar, "ask_delete_char");
1803 // ------------------------------------------------------------------------------------------------
1804 string getTarget(CCtrlBase * /* ctrl */, const string &targetName)
1806 string sTmp = targetName;
1807 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1808 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1810 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1812 CInterfaceElement *elem = rTI.Elem;
1813 if (!elem)
1815 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1816 return "";
1818 const CReflectedProperty *pRP = CReflectSystem ::getProperty(elem->getReflectedClassName(), rTI.PropertyName);
1820 if (pRP->Type == CReflectedProperty::String)
1821 return ((elem->*(pRP->GetMethod.GetString))());
1822 return "";
1825 #ifdef RYZOM_LUA_UCSTRING
1826 // ------------------------------------------------------------------------------------------------
1827 ucstring getUCTarget(CCtrlBase * /* ctrl */, const string &targetName)
1829 string sTmp = targetName;
1830 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1831 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1833 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1835 CInterfaceElement *elem = rTI.Elem;
1836 if (!elem)
1838 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1839 return ucstring(""); // TODO: UTF-8 Lua
1841 const CReflectedProperty *pRP = elem->getReflectedProperty(rTI.PropertyName);
1843 if (pRP->Type == CReflectedProperty::UCString)
1844 return ((elem->*(pRP->GetMethod.GetUCString))());
1845 return ucstring(""); // TODO: UTF-8 Lua
1847 #endif
1849 /*// Ask the server to rename a character
1850 // ------------------------------------------------------------------------------------------------
1851 class CAHAskRenameChar : public IActionHandler
1853 public:
1854 virtual void execute (CCtrlBase *pCaller, const string &Params)
1856 string sName = getTarget(NULL,getParam(Params, "name"));
1857 string sSurname = getTarget(NULL,getParam(Params, "surname"));
1859 string sDBSlot = getParam(Params, "dbslot");
1861 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1862 uint8 nSelectedSlot = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sDBSlot,false)->getValue32();
1864 if (nSelectedSlot > CharacterSummaries.size())
1865 return;
1867 // Create the message for the server to create the character.
1868 CBitMemStream out;
1869 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:RENAME_CHAR", out))
1871 nlwarning ("don't know message name CONNECTION:RENAME_CHAR");
1872 return;
1875 // Get the selected slot
1876 out.serial (nSelectedSlot);
1877 out.serial (sName);
1878 out.serial (sSurname);
1880 // Send the message to the server
1881 if (!ClientCfg.Light)
1883 noUserChar = userChar = false;
1884 NetMngr.push (out);
1885 NetMngr.send (NetMngr.getCurrentServerTick());
1887 nldebug("impulseCallBack : CONNECTION:RENAME_CHAR sent");
1889 // Wait for the character message which describe all the characters on a server
1890 while (!noUserChar && !userChar)
1892 //NetMngr.waitForServer();
1893 NetMngr.update();
1894 NetMngr.send();
1895 nlSleep(100);
1898 else
1900 CharacterSummaries[nSelectedSlot].FirstName = sName;
1901 CharacterSummaries[nSelectedSlot].Surname = sSurname;
1905 REGISTER_ACTION_HANDLER (CAHAskRenameChar, "ask_rename_char");
1908 // Ask the server if the name is not already used
1909 // ------------------------------------------------------------------------------------------------
1910 class CAHAskValidName : public IActionHandler
1912 public:
1913 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1915 string sTarget = getParam(Params, "target");
1916 string sDBLink = getParam(Params, "dblink");
1917 CharNameValidDBLink = sDBLink;
1919 #ifdef RYZOM_LUA_UCSTRING
1920 string sName = getUCTarget(NULL,sTarget).toUtf8(); // TODO: UTF-8 Lua
1921 #else
1922 string sName = getTarget(NULL, sTarget);
1923 #endif
1925 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1926 if (sName.empty())
1928 NLGUI::CDBManager::getInstance()->getDbProp(sDBLink,false)->setValue32(0);
1929 return;
1932 // Ask the server
1933 CharNameValid = true;
1935 // PATCH DU BUG DE L'ESPACE !!!
1936 if (sName.find(' ') != ucstring::npos)
1937 CharNameValid = false;
1938 // PATCH DU BUG DE L'ESPACE !!!
1941 if (CharNameValid)
1943 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1946 CBitMemStream out;
1947 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ASK_NAME", out))
1949 nlwarning ("don't know message name CONNECTION:ASK_NAME");
1950 return;
1953 CCheckNameMsg checkNameMsg;
1954 checkNameMsg.Name = sName;
1955 checkNameMsg.HomeSessionId = MainlandSelected;
1956 checkNameMsg.serialBitMemStream(out);
1958 NewKeysCharNameWanted = sName;
1959 // append shard name
1960 for(uint k = 0; k < Mainlands.size(); ++k)
1962 if (Mainlands[k].Id == MainlandSelected)
1964 // extract name from mainland
1965 /*ucstring::size_type first = Mainlands[k].Name.find('('); // OLD
1966 ucstring::size_type last = Mainlands[k].Name.find(')');// OLD
1967 if (first != ucstring::npos && last != ucstring::npos && first < last)// OLD
1969 NewKeysCharNameWanted += Mainlands[k].Name.substr(first, last - first + 1);
1971 NewKeysCharNameWanted += ('(' + Mainlands[k].Name.toUtf8() + ')');
1972 break;
1976 NewKeysCharNameValidated.clear();
1978 NetMngr.push(out);
1979 NetMngr.send(NetMngr.getCurrentServerTick());
1981 //nlinfo("impulseCallBack : CONNECTION:ASK_NAME sent");
1983 // Wait for the valid character name message
1984 CharNameValidArrived = false;
1986 else
1989 CharNameValid = true;
1990 CharNameValidArrived = true;
1992 for (uint i = 0; i < CharacterSummaries.size(); ++i)
1994 string ls = CharacterSummaries[i].Name.toString();
1995 if (ls == sName)
1996 CharNameValid = false;
2000 else
2002 CharNameValidArrived = true;
2004 WaitServerAnswer = true;
2007 REGISTER_ACTION_HANDLER (CAHAskValidName, "ask_valid_name");
2009 // ------------------------------------------------------------------------------------------------
2010 class CAHPlaySound : public IActionHandler
2012 public:
2013 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2015 string sName = getParam(Params, "name");
2016 TStringId id = CStringMapper::map(sName);
2017 if (SoundMngr != NULL)
2018 SoundMngr->spawnSource(id,CVector(0,0,0));
2021 REGISTER_ACTION_HANDLER (CAHPlaySound, "play_sound");
2023 // ------------------------------------------------------------------------------------------------
2024 class CAHPlayMusicOutgame : public IActionHandler
2026 public:
2027 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2029 // get the name of the wanted music
2030 string sName = getParam(Params, "name");
2031 bool async;
2032 fromString(getParam(Params, "async"), async);
2034 // if empty name, return to default mode
2035 if (sName.empty())
2036 sName = ClientCfg.EmptySlotMusic;
2038 // change the music
2039 SoundGlobalMenu.setMusic(sName, async);
2042 REGISTER_ACTION_HANDLER (CAHPlayMusicOutgame, "play_music_outgame");
2044 // ------------------------------------------------------------------------------------------------
2045 class CAHRepeatUntil : public IActionHandler
2047 public:
2048 virtual void execute (CCtrlBase *pCaller, const string &Params)
2050 string sProc = getParam(Params, "proc");
2051 string sCond = getParam(Params, "cond");
2052 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2054 for(;;)
2056 vector<string> p;
2057 p.push_back(sProc);
2058 CWidgetManager::getInstance()->runProcedure(sProc, pCaller, p);
2060 CInterfaceExprValue result;
2061 if (CInterfaceExpr::eval(sCond, result))
2063 if (result.getBool())
2064 break;
2066 else
2068 break;
2074 REGISTER_ACTION_HANDLER (CAHRepeatUntil, "repeatuntil");
2077 // ------------------------------------------------------------------------------------------------
2078 class CAHDispInfo : public IActionHandler
2080 public:
2081 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2083 string sStr = getParam(Params, "str");
2084 string sVal = getParam(Params, "val");
2086 string res;
2088 CInterfaceExprValue result;
2089 if (CInterfaceExpr::eval(sStr, result))
2091 if (result.toString())
2093 res += result.getString();
2096 if (CInterfaceExpr::eval(sVal, result))
2098 if (result.toString())
2100 res += result.getString();
2104 nlinfo(res.c_str());
2107 REGISTER_ACTION_HANDLER (CAHDispInfo, "disp_info");
2110 // ***************************************************************************
2111 class CAHInitMainlandList : public IActionHandler
2113 public:
2115 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2117 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2119 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2120 if (pList == NULL)
2122 nlwarning("element " GROUP_LIST_MAINLAND " not found probably bad outgame.xml");
2123 return;
2126 CInterfaceGroup *pPrevLine = NULL;
2127 for(uint i = 0; i < Mainlands.size(); i++)
2129 vector< pair < string, string > > params;
2130 params.clear();
2131 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2132 if (i>0)
2133 params.push_back(pair<string,string>("posref", "BL TL"));
2135 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_mainland", GROUP_LIST_MAINLAND, params);
2136 if (pNewLine != NULL)
2138 CViewBase *pVBon = pNewLine->getView("online");
2139 CViewBase *pVBoff = pNewLine->getView("offline");
2140 if ((pVBon != NULL) && (pVBoff != NULL))
2142 pVBon->setActive(Mainlands[i].Online);
2143 pVBoff->setActive(!Mainlands[i].Online);
2146 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2147 if (pVT != NULL)
2149 std::string str = Mainlands[i].Name.toUtf8() + " " + Mainlands[i].Description.toUtf8();
2150 pVT->setTextLocalized(str, false);
2153 // Add to the list
2154 pNewLine->setParent(pList);
2155 pNewLine->setParentSize(pList);
2156 pNewLine->setParentPos(pPrevLine);
2157 pList->addGroup(pNewLine);
2159 pPrevLine = pNewLine;
2162 // UI Patch
2163 if (!Mainlands.empty())
2165 //choose default mainland from language code
2166 uint32 defaultMainland = 0;
2167 for(uint i = 0; i < Mainlands.size(); i++)
2169 if( Mainlands[i].LanguageCode == ClientCfg.LanguageCode )
2171 defaultMainland = i;
2172 break;
2176 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(Mainlands[defaultMainland].Id)+":but"));
2177 if (pCB != NULL)
2179 pCB->setPushed(true);
2180 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2183 pList->invalidateCoords();
2186 REGISTER_ACTION_HANDLER (CAHInitMainlandList, "init_mainland_list");
2189 // ***************************************************************************
2190 class CAHResetMainlandList : public IActionHandler
2192 public:
2194 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2196 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2197 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2198 pList->clearGroups();
2201 REGISTER_ACTION_HANDLER (CAHResetMainlandList, "reset_mainland_list");
2204 // ***************************************************************************
2205 class CAHMainlandSelect : public IActionHandler
2207 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2209 nlinfo("CAHMainlandSelect called");
2211 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2213 CCtrlButton *pCB = NULL;
2214 // Unselect
2215 if (MainlandSelected.asInt() != 0)
2217 pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(MainlandSelected)+":but"));
2218 if (pCB != NULL)
2219 pCB->setPushed(false);
2222 pCB = dynamic_cast<CCtrlButton*>(pCaller);
2223 if (pCB != NULL)
2225 string name = pCB->getId();
2226 name = name.substr(0,name.rfind(':'));
2227 uint32 mainland;
2228 fromString(name.substr(name.rfind(':')+1,name.size()), mainland);
2229 MainlandSelected = (TSessionId)mainland;
2231 pCB->setPushed(true);
2235 REGISTER_ACTION_HANDLER (CAHMainlandSelect, "mainland_select");
2238 // ***************************************************************************
2239 class CAHInitKeysetList : public IActionHandler
2241 public:
2245 CInterfaceGroup *PrevLine;
2246 CInterfaceGroup *List;
2247 bool First;
2249 CInterfaceGroup *buildTemplate(const std::string &templateName, const std::string &id)
2251 vector< pair < string, string > > params;
2252 params.clear();
2253 params.push_back(pair<string,string>("id", id));
2254 if (!First)
2256 params.push_back(pair<string,string>("posref", "BL TL"));
2258 First = false;
2259 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2260 return CWidgetManager::getInstance()->getParser()->createGroupInstance(templateName, GROUP_LIST_KEYSET, params);
2263 void addGroupInList(CInterfaceGroup *pNewLine)
2265 if (!pNewLine) return;
2266 // Add to the list
2267 pNewLine->setParent(List);
2268 pNewLine->setParentSize(List);
2269 pNewLine->setParentPos(PrevLine);
2270 List->addGroup(pNewLine);
2272 PrevLine = pNewLine;
2275 void addSeparator()
2277 addGroupInList(buildTemplate("t_keyseparator", ""));
2280 // add a new keyset in the list
2281 void addKeySet(const std::string &filename, const std::string &name, const std::string tooltip)
2283 nlassert(List);
2284 CInterfaceGroup *pNewLine = buildTemplate("t_keyset", toString(filename));
2285 if (pNewLine != NULL)
2287 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2288 if (pVT != NULL)
2290 pVT->setTextLocalized(name, false);
2293 CCtrlBase *pBut = pNewLine->getCtrl("but");
2294 if (pBut != NULL)
2296 pBut->setDefaultContextHelp(tooltip);
2298 addGroupInList(pNewLine);
2302 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2304 NewKeysCharNameWanted.clear();
2305 NewKeysCharNameValidated.clear();
2306 GameKeySet = "keys.xml";
2307 RingEditorKeySet = "keys_r2ed.xml";
2308 First = true;
2309 PrevLine = NULL;
2310 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2312 List = dynamic_cast<CInterfaceGroup *>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2313 if (List == NULL)
2315 nlwarning("element " GROUP_LIST_KEYSET " not found probably bad outgame.xml");
2316 return;
2319 // built-in keysets
2320 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2321 sint wasdIndex = -1;
2322 sint zqsdIndex = -1;
2323 if (keySetVar && keySetVar->size() != 0)
2325 for (uint k = 0; k < keySetVar->size(); ++k)
2327 if (keySetVar->asString(k) == "zqsd") zqsdIndex = (sint) k;
2328 if (keySetVar->asString(k) == "wasd") wasdIndex = (sint) k;
2330 std::string strId = "uiCP_KeysetName_" + keySetVar->asString(k);
2331 strFindReplace(strId, ".", "_");
2332 const string &keySetName = CI18N::get(strId);
2333 strId = "uiCP_KeysetTooltip_" + keySetVar->asString(k);
2334 strFindReplace(strId, ".", "_");
2335 if (CI18N::hasTranslation(strId))
2337 const string &keySetTooltip = CI18N::get(strId);
2338 addKeySet(keySetVar->asString(k), keySetName, keySetTooltip);
2342 else
2344 nlwarning("'%s' var not found in config file, or list is empty, proposing default keyset only", KeySetVarName);
2345 std::string defaultKeySet = "keys";
2346 const string &keySetName = CI18N::get("uiCP_KeysetName_" + defaultKeySet);
2347 const string &keySetTooltip = CI18N::get("uiCP_KeysetTooltip_" + defaultKeySet);
2348 addKeySet(defaultKeySet, keySetName, keySetTooltip);
2351 // keyset from previous chars
2352 std::vector<std::string> savedFiles;
2353 CPath::getPathContent("save/", false, false, true, savedFiles);
2354 enum { GameKeys = 0x1, EditorKeys = 0x2 };
2355 typedef std::map<std::string, uint> TKeySetFileMap;
2356 TKeySetFileMap keySetFiles; // combination of 'GameKeys' & 'EditorKeys' flag for each character
2357 for (uint k = 0; k < savedFiles.size(); ++k)
2359 if (testWildCard(CFile::getFilename(savedFiles[k]), "keys_*.xml"))
2361 bool editorKeys = testWildCard(CFile::getFilename(savedFiles[k]), "keys_r2ed_*.xml");
2362 std::string baseName = CFile::getFilenameWithoutExtension(savedFiles[k]).substr(strlen(editorKeys ? "keys_r2ed_" : "keys_"));
2363 if(!keySetFiles.count(baseName)) keySetFiles[baseName] = 0;
2364 keySetFiles[baseName] |= editorKeys ? EditorKeys : GameKeys;
2368 bool separatorAdded = false;
2369 if (!keySetFiles.empty())
2371 for(TKeySetFileMap::iterator it = keySetFiles.begin(); it != keySetFiles.end(); ++it)
2373 string name;
2374 if (ClientCfg.Local)
2376 name = it->first;
2378 else
2380 // search matching utf-8 string name from character summaries
2381 for (uint k = 0; k < CharacterSummaries.size(); ++k)
2383 if (it->first == buildPlayerNameForSaveFile(CharacterSummaries[k].Name.toUtf8()))
2385 name = CharacterSummaries[k].Name.toUtf8();
2389 if (!name.empty())
2391 if (!separatorAdded)
2393 addSeparator();
2394 separatorAdded = true;
2396 addKeySet(it->first, it->first, CI18N::get(std::string("uiCP_KeysetImport") + (it->second & GameKeys ? "_Game" : "")
2397 + (it->second & EditorKeys ? "_Editor" : "")));
2402 // default to 'ZQSD' for French and Belgian keyboard, 'WASD' else
2403 bool wasd = !CSystemUtils::isAzertyKeyboard();
2405 /*sint startIndex = wasd ? wasdIndex : zqsdIndex;
2406 if (startIndex == -1) startIndex = 0;
2408 // TMP TMP : no way to have 2 keys for the same action for now -> default to 'arrows' setting.
2409 sint startIndex = 0;
2410 nlassert(startIndex >= 0);
2411 if (startIndex < (sint) List->getNumGroup())
2413 CInterfaceGroup *gr = dynamic_cast<CInterfaceGroup *>(List->getGroup(startIndex));
2414 if (gr)
2416 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(gr->getCtrl("but"));
2417 if (pCB != NULL)
2419 pCB->setPushed(true);
2420 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2424 List->invalidateCoords();
2427 REGISTER_ACTION_HANDLER (CAHInitKeysetList, "init_keyset_list");
2430 // ***************************************************************************
2431 class CAHResetKeysetList : public IActionHandler
2433 public:
2435 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2437 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2438 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2439 pList->clearGroups();
2442 REGISTER_ACTION_HANDLER (CAHResetKeysetList, "reset_keyset_list");
2445 // ***************************************************************************
2446 class CAHResetKeysetSelect : public IActionHandler
2448 public:
2449 std::string getIdPostFix(const std::string fullId)
2451 std::string::size_type pos = fullId.find_last_of(":");
2452 if (pos != std::string::npos)
2454 return fullId.substr(pos + 1);
2456 return "";
2458 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2460 if (!pCaller) return;
2461 // 'unpush' all groups but the caller
2463 struct CUnpush : public CInterfaceElementVisitor
2465 CCtrlBase *Ref;
2466 virtual void visitCtrl(CCtrlBase *ctrl)
2468 if (ctrl == Ref) return;
2469 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton *>(ctrl);
2470 if (but)
2472 but->setPushed(false);
2476 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2477 CInterfaceGroup * list = dynamic_cast<CInterfaceGroup *>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2478 if (list)
2480 CUnpush unpusher;
2481 unpusher.Ref = pCaller;
2482 list->visit(&unpusher);
2484 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton *>(pCaller);
2485 if (but)
2487 but->setPushed(true);
2490 GameKeySet = "keys.xml";
2491 RingEditorKeySet = "keys_r2ed.xml";
2492 if (!pCaller->getParent()) return;
2493 // compute the 2 filenames from the id
2494 // if id is in the built-in keysets :
2495 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2496 if (keySetVar && keySetVar->size() != 0)
2498 for (uint k = 0; k < keySetVar->size(); ++k)
2500 std::string id = getIdPostFix(pCaller->getParent()->getId());
2501 if (keySetVar->asString(k) == id)
2503 GameKeySet = "keys" + string(id.empty() ? "" : "_") + id + ".xml";
2504 RingEditorKeySet = "keys_r2ed" + string(id.empty() ? "" : "_") + id + ".xml";
2505 return;
2509 // ... else maybe from a previous character ?
2510 if (CFile::isExists("save/keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") )
2512 GameKeySet = "keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml";
2514 if (CFile::isExists("save/keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") )
2516 RingEditorKeySet = "keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml";
2518 // NB : key file will be copied for real when the new 'character summary' is
2522 REGISTER_ACTION_HANDLER (CAHResetKeysetSelect, "keyset_select");
2528 // *************************** SCENARIO CONTROL WINDOW ***********************
2529 // ***************************************************************************
2530 // helper function for "setScenarioInformation"
2531 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const std::string &text)
2533 CInterfaceElement *result = scenarioWnd->findFromShortId(uiName);
2534 if(result)
2536 CViewText* viewText = dynamic_cast<CViewText*>(result);
2537 if(viewText)
2538 viewText->setTextLocalized(text, false);
2539 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2540 if(editBox)
2541 editBox->setInputString(text);
2545 // helper function for "setScenarioInformation"
2546 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const ucstring &text) // TODO: UTF-8 Lua
2548 setTextField(scenarioWnd, uiName, text.toUtf8());
2550 // helper function for "setScenarioInformation"
2551 static std::string fieldLookup(const vector< pair< string, string > > &values, const std::string &id)
2553 for(uint i=0; i<values.size(); i++)
2555 if (values[i].first == id) return values[i].second;
2557 return "--";
2560 static void setScenarioInformation(CInterfaceGroup* scenarioWnd, const string scenarioName)
2562 vector< pair< string, string > > values;
2563 if(R2::getEditor().isInitialized())
2565 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
2567 else
2569 R2::CScenarioValidator sv;
2570 std::string md5, signature;
2571 sv.setScenarioToLoad(scenarioName, values, md5, signature, false);
2574 setTextField(scenarioWnd, "rules_value_text", fieldLookup(values, "Rules"));
2575 uint levelRange = 0;
2576 uint32 nLevel;
2577 fromString(fieldLookup(values, "Level"), nLevel);
2578 switch(nLevel)
2580 case 20: levelRange = 0; break;
2581 case 50: levelRange = 1; break;
2582 case 100: levelRange = 2; break;
2583 case 150: levelRange = 3; break;
2584 case 200: levelRange = 4; break;
2585 case 250: levelRange = 5; break;
2587 setTextField(scenarioWnd, "level_value_text", CI18N::get("uiRAP_Level" + toString(levelRange)));
2588 setTextField(scenarioWnd, "language_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Language")));
2589 setTextField(scenarioWnd, "type_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Type")));
2590 setTextField(scenarioWnd, "edit_small_description", fieldLookup(values, "ShortDescription"));
2591 if(R2::getEditor().isInitialized())
2593 setTextField(scenarioWnd, "scenario_value_text", "'" + fieldLookup(values, "Title") + "'");
2598 void getChildrenControls(CInterfaceGroup* group, std::vector<CCtrlBase*> & controls)
2600 for(uint i=0; i<group->getGroups().size(); i++)
2601 getChildrenControls(group->getGroups()[i], controls);
2603 for(uint i=0; i<group->getControls().size(); i++)
2604 controls.push_back(group->getControls()[i]);
2607 inline void setToggleButton(CInterfaceGroup* scenarioWnd, const string & buttonName, bool pushed)
2609 CInterfaceElement * result = scenarioWnd->findFromShortId(buttonName);
2610 if(result)
2612 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
2613 if(group)
2615 result = group->findFromShortId(string("toggle_butt"));
2616 if(result)
2618 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2619 if(baseButton)
2620 baseButton->setPushed(!pushed);
2627 class CAHScenarioControl : public IActionHandler
2629 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2631 nlinfo("CAHScenarioControl called");
2633 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2634 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2635 if(!scenarioWnd) return;
2637 // -------- active some groups in function of Ryzom mode or Edition/Animation mode ----
2638 // active team toggle button?
2639 CInterfaceElement *result = scenarioWnd->findFromShortId(string("invite_team"));
2640 if(result)
2642 CInterfaceGroup* groupTeam = dynamic_cast<CInterfaceGroup*>(result);
2643 if(groupTeam)
2645 bool team = !(R2::getEditor().isInitialized());
2646 if(team)
2647 team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2648 groupTeam->setActive(team);
2652 // set scenario name label
2653 result = scenarioWnd->findFromShortId(string("current_scenario_label_text"));
2654 if(result)
2656 CViewText* viewText = dynamic_cast<CViewText*>(result);
2657 if(viewText)
2659 viewText->setTextLocalized(R2::getEditor().isInitialized() ? "uiR2EDScenarioName" : "uiR2EDScenarioFileName", true);
2663 // ok button tranlation
2664 result = scenarioWnd->findFromShortId(string("ok_button"));
2665 if(result)
2667 CCtrlTextButton* okButton = dynamic_cast<CCtrlTextButton*>(result);
2668 if(okButton)
2670 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
2671 okButton->setHardText(CI18N::get("uiR2EDLaunchScenario"));
2672 else
2673 okButton->setHardText(CI18N::get("uiR2EDApplyScenarioFilters"));
2677 // init current scenario name and parameters
2678 if(!R2::getEditor().isInitialized())
2680 ScenarioFileName.clear();
2682 // empty scenario
2683 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2684 if(result)
2686 CViewText* viewText= dynamic_cast<CViewText*>(result);
2688 if(viewText)
2689 viewText->setText(std::string());
2692 setScenarioInformation(scenarioWnd, "");
2694 // hide description and information?
2695 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2696 if(result)
2697 result->setActive(R2::getEditor().isInitialized());
2699 result = scenarioWnd->findFromShortId(string("description_gr"));
2700 if(result)
2701 result->setActive(R2::getEditor().isInitialized());
2703 // mainlands list
2704 result = scenarioWnd->findFromShortId(string("shards"));
2705 if(result)
2707 CGroupList * shardList = dynamic_cast<CGroupList*>(result);
2708 if(shardList)
2710 shardList->deleteAllChildren();
2712 for(uint i = 0; i < Mainlands.size(); i++)
2714 vector< pair < string, string > > params;
2715 params.clear();
2716 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2717 params.push_back(pair<string,string>("w", "1024"));
2718 params.push_back(pair<string,string>("tooltip", "uiRingFilterShard"));
2719 CInterfaceGroup *toggleGr = CWidgetManager::getInstance()->getParser()->createGroupInstance("label_toggle_button", shardList->getId(), params);
2720 shardList->addChild(toggleGr);
2721 // set unicode name
2722 CViewText *shardName = dynamic_cast<CViewText *>(toggleGr->getView("button_text"));
2723 if (shardName)
2725 shardName->setTextLocalized(Mainlands[i].Name.toUtf8(), false);
2731 // show/display "back" button
2732 result = scenarioWnd->findFromShortId(string("load_button"));
2733 if(result)
2735 CCtrlBaseButton * loadB = dynamic_cast<CCtrlBaseButton *>(result);
2736 if(loadB)
2738 loadB->setActive(!R2::getEditor().isInitialized());
2742 // fill toggle buttons
2743 if(R2::getEditor().getAccessMode()==R2::CEditor::AccessDM)
2745 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
2746 sessionBrowser.getSessionInfo(sessionBrowser.getCharId(), R2::getEditor().getDMC().getEditionModule().getCurrentAdventureId());
2748 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_sessionInfoResult")))
2750 TRaceFilter & raceFilter = sessionBrowser._LastRaceFilter;
2751 setToggleButton(scenarioWnd, "fyros", raceFilter.checkEnumValue(TRaceFilterEnum::rf_fyros));
2752 setToggleButton(scenarioWnd, "matis", raceFilter.checkEnumValue(TRaceFilterEnum::rf_matis));
2753 setToggleButton(scenarioWnd, "tryker", raceFilter.checkEnumValue(TRaceFilterEnum::rf_tryker));
2754 setToggleButton(scenarioWnd, "zorai", raceFilter.checkEnumValue(TRaceFilterEnum::rf_zorai));
2756 TReligionFilter & religionFilter = sessionBrowser._LastReligionFilter;
2757 setToggleButton(scenarioWnd, "kami", religionFilter.checkEnumValue(TReligionFilterEnum::rf_kami));
2758 setToggleButton(scenarioWnd, "karavan", religionFilter.checkEnumValue(TReligionFilterEnum::rf_karavan));
2759 setToggleButton(scenarioWnd, "neutral", religionFilter.checkEnumValue(TReligionFilterEnum::rf_neutral));
2761 TGuildFilter & guildFilter = sessionBrowser._LastGuildFilter;
2762 setToggleButton(scenarioWnd, "guild_gr", (guildFilter==TGuildFilter::gf_any_player));
2764 TShardFilter & shardFilter = sessionBrowser._LastShardFilter;
2765 for(uint i=0; i<Mainlands.size(); i++)
2766 setToggleButton(scenarioWnd, toString(Mainlands[i].Id), shardFilter.checkEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i)));
2768 TLevelFilter & levelFilter = sessionBrowser._LastLevelFilter;
2769 setToggleButton(scenarioWnd, "20", levelFilter.checkEnumValue(TLevelFilterEnum::lf_a));
2770 setToggleButton(scenarioWnd, "50", levelFilter.checkEnumValue(TLevelFilterEnum::lf_b));
2771 setToggleButton(scenarioWnd, "100", levelFilter.checkEnumValue(TLevelFilterEnum::lf_c));
2772 setToggleButton(scenarioWnd, "150", levelFilter.checkEnumValue(TLevelFilterEnum::lf_d));
2773 setToggleButton(scenarioWnd, "200", levelFilter.checkEnumValue(TLevelFilterEnum::lf_e));
2774 setToggleButton(scenarioWnd, "250", levelFilter.checkEnumValue(TLevelFilterEnum::lf_f));
2776 bool subscriptionClosed = sessionBrowser._LastSubscriptionClosed;
2777 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2778 if(result)
2780 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2781 if(baseButton)
2782 baseButton->setPushed(subscriptionClosed);
2785 bool autoInvite = sessionBrowser._LastAutoInvite;
2786 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2787 if(result)
2789 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2790 if(baseButton)
2791 baseButton->setPushed(!autoInvite);
2794 // description
2795 string description = sessionBrowser._LastDescription;
2796 if(!description.empty())
2798 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2799 if(result)
2801 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2802 if(editBox)
2803 editBox->setInputString(description);
2807 else
2809 nlwarning("getSessionInfo callback return false");
2812 else
2814 result = scenarioWnd->findFromShortId(string("access_players_filter"));
2815 if(result)
2817 CInterfaceGroup* filtersGroup = dynamic_cast<CInterfaceGroup*>(result);
2818 if(filtersGroup)
2820 std::vector<CCtrlBase*> controls;
2821 getChildrenControls(filtersGroup, controls);
2822 for(uint i=0; i<controls.size(); i++)
2824 CCtrlBase* control = controls[i];
2825 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(control);
2826 if(baseButton && (baseButton->getType()==CCtrlBaseButton::ToggleButton))
2827 baseButton->setPushed(false);
2834 REGISTER_ACTION_HANDLER (CAHScenarioControl, "init_scenario_control");
2837 // ***************************************************************************
2838 class CAHScenarioInformation : public IActionHandler
2840 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2842 nlinfo("CAHScenarioDescription called");
2844 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2845 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2846 if(!scenarioWnd) return;
2848 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2849 if(result)
2851 CViewText* viewText= dynamic_cast<CViewText*>(result);
2853 if(viewText)
2855 ScenarioFileName = getParam(Params, "ScenarioName");
2856 setScenarioInformation(scenarioWnd, ScenarioFileName);
2858 string scenarioName = ScenarioFileName;
2859 string::size_type posScenarioName = 0;
2860 while(posScenarioName!=string::npos)
2862 scenarioName = scenarioName.substr(posScenarioName==0?posScenarioName:posScenarioName+1);
2863 posScenarioName = scenarioName.find('/');
2865 viewText->setTextLocalized(scenarioName, false);
2869 // active description and information
2870 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2871 if(result)
2872 result->setActive(true);
2874 result = scenarioWnd->findFromShortId(string("description_gr"));
2875 if(result)
2876 result->setActive(true);
2879 REGISTER_ACTION_HANDLER (CAHScenarioInformation, "scenario_information");
2881 // ***************************************************************************
2882 class CAHHideCharsFilters : public IActionHandler
2884 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2886 nlinfo("CAHHideCharsFilters called");
2888 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2889 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2890 if(!scenarioWnd) return;
2892 bool lookingForPlayers = true;
2893 CInterfaceElement *result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2894 if(result)
2896 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2897 if(baseButton)
2898 lookingForPlayers = !baseButton->getPushed(); // warning : on / off textures are inverted !!!
2901 result = scenarioWnd->findFromShortId(string("access_body_gr"));
2902 if(result)
2903 result->setActive(lookingForPlayers);
2905 result = scenarioWnd->findFromShortId(string("sep_global_access"));
2906 if(result)
2907 result->setActive(lookingForPlayers);
2909 result = scenarioWnd->findFromShortId(string("auto_invite_label"));
2910 if(result)
2911 result->setActive(lookingForPlayers);
2913 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2914 if(result)
2915 result->setActive(lookingForPlayers);
2917 result = scenarioWnd->findFromShortId(string("invite_team"));
2918 if(result)
2920 bool team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2921 team = (team && !(R2::getEditor().isInitialized()) && lookingForPlayers);
2922 result->setActive(team);
2926 REGISTER_ACTION_HANDLER (CAHHideCharsFilters, "hide_chars_filters");
2928 // ***************************************************************************
2929 class CAHLoadScenario : public IActionHandler
2931 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2933 nlinfo("CAHLoadScenario called");
2935 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2936 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2937 if(!scenarioWnd) return;
2939 CInterfaceElement *result = NULL;
2941 // load scenario
2942 if(!R2::getEditor().isInitialized())
2944 R2::CEditor::setStartingAnimationFilename(ScenarioFileName);
2947 // description
2948 string description;
2949 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2950 if(result)
2952 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2953 if(editBox)
2954 description = editBox->getInputString();
2957 // races
2958 map<string, bool> races;
2959 races["fyros"] = false;
2960 races["matis"] = false;
2961 races["tryker"] = false;
2962 races["zorai"] = false;
2963 for(map<string, bool>::iterator itRace=races.begin(); itRace!=races.end(); itRace++)
2965 result = scenarioWnd->findFromShortId(itRace->first);
2966 if(result)
2968 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
2969 if(group)
2971 result = group->findFromShortId(string("toggle_butt"));
2972 if(result)
2974 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2975 if(baseButton)
2976 itRace->second = !baseButton->getPushed();
2982 // religion
2983 map<string, bool> religions;
2984 religions["kami"] = false;
2985 religions["karavan"] = false;
2986 religions["neutral"] = false;
2987 for(map<string, bool>::iterator itReligion=religions.begin(); itReligion!=religions.end(); itReligion++)
2989 result = scenarioWnd->findFromShortId(itReligion->first);
2990 if(result)
2992 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
2993 if(group)
2995 result = group->findFromShortId(string("toggle_butt"));
2996 if(result)
2998 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2999 if(baseButton)
3000 itReligion->second = !baseButton->getPushed();
3006 // guild
3007 bool anyPlayer = false;
3008 result = scenarioWnd->findFromShortId(string("guild_gr"));
3009 if(result)
3011 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3012 if(group)
3014 result = group->findFromShortId(string("toggle_butt"));
3015 if(result)
3017 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3018 if(baseButton)
3019 anyPlayer = !baseButton->getPushed();
3024 // shards
3025 std::vector<bool> shards(Mainlands.size(), false);
3026 for(uint i=0; i<Mainlands.size(); i++)
3028 string firstKey = Mainlands[i].Description.toString();
3030 result = scenarioWnd->findFromShortId(toString(Mainlands[i].Id));
3031 if(result)
3033 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3034 if(group)
3036 result = group->findFromShortId(string("toggle_butt"));
3037 if(result)
3039 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3040 if(baseButton)
3041 shards[i] = !baseButton->getPushed();
3047 // levels
3048 map<string, bool> levels;
3049 levels["20"] = false;
3050 levels["50"] = false;
3051 levels["100"] = false;
3052 levels["150"] = false;
3053 levels["200"] = false;
3054 levels["250"] = false;
3055 for(map<string, bool>::iterator itLevel=levels.begin(); itLevel!=levels.end(); itLevel++)
3057 result = scenarioWnd->findFromShortId(itLevel->first);
3058 if(result)
3060 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3061 if(group)
3063 result = group->findFromShortId(string("toggle_butt"));
3064 if(result)
3066 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3067 if(baseButton)
3068 itLevel->second = !baseButton->getPushed();
3074 // global access
3075 bool globalAccess = false;
3076 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
3077 if(result)
3079 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3080 if(baseButton)
3081 globalAccess = !baseButton->getPushed();
3084 // auto invite
3085 bool autoInvite = false;
3086 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
3087 if(result)
3089 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3090 if(baseButton)
3091 autoInvite = !baseButton->getPushed();
3094 // invite your team
3095 bool inviteTeam = false;
3096 result = scenarioWnd->findFromShortId(string("team_toggle_butt"));
3097 if(result)
3099 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3100 if(baseButton)
3101 inviteTeam = !baseButton->getPushed();
3104 bool launchScenarioFromRingAccessPoint = false;
3106 vector< pair< string, string > > values;
3107 if(R2::getEditor().isInitialized())
3109 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
3111 else
3113 R2::CScenarioValidator sv;
3114 std::string md5, signature;
3115 sv.setScenarioToLoad(ScenarioFileName, values, md5, signature, false);
3116 launchScenarioFromRingAccessPoint = true;
3119 string rules, level, title;
3120 string initialIsland, initialEntryPoint, initialSeason;
3121 std::string lang, scenarioType;
3122 std::string otherCharAccess;
3123 std::string nevraxScenario = "0";
3124 std::string trialAllowed = "0";
3125 for(uint i=0; i<values.size(); i++)
3127 std::pair<std::string, std::string> pair = values[i];
3129 if(pair.first == "Rules") rules = pair.second;
3130 else if(pair.first == "Level") level = pair.second;
3131 else if(pair.first == "Title") title = pair.second;
3132 else if(pair.first == "InitialIsland") initialIsland = pair.second;
3133 else if(pair.first == "InitialEntryPoint") initialEntryPoint = pair.second;
3134 else if(pair.first == "InitialSeason") initialSeason = pair.second;
3135 else if(pair.first == "Language") lang = pair.second;
3136 else if(pair.first == "Type") scenarioType = pair.second;
3137 else if(pair.first == "OtherCharAccess") otherCharAccess = pair.second;
3138 else if(pair.first == "NevraxScenario") nevraxScenario = pair.second;
3139 else if(pair.first == "TrialAllowed") trialAllowed = pair.second;
3142 uint nLevel;
3143 fromString(level, nLevel);
3144 R2::TSessionLevel sessionLevel = R2::TSessionLevel::TValues(nLevel/50 + 1);
3146 // ---- fix for old scenarii
3147 if (lang == "French")
3148 lang = "fr";
3149 else if (lang == "German" || lang == "Deutsch")
3150 lang = "de";
3151 else //if (lang == "English")
3152 lang = "en";
3154 if (nlstricmp(scenarioType, "Roleplay") == 0 || nlstricmp(scenarioType, "Role play") == 0)
3155 scenarioType = "so_story_telling";
3156 else if (nlstricmp(scenarioType, "Combat") == 0)
3157 scenarioType = "so_hack_slash";
3158 // --------------------------
3160 TRuleType ruleType(TRuleType::rt_strict);
3161 if(rules==CI18N::get("uiR2EDliberal"))
3162 ruleType = TRuleType(TRuleType::rt_liberal);
3163 else if(rules == CI18N::get("uiR2EDstrict"))
3164 ruleType = TRuleType(TRuleType::rt_strict);
3165 volatile static bool override = false;
3166 if (override)
3168 if(rules== "Masterless")
3169 ruleType = TRuleType(TRuleType::rt_liberal);
3170 else if(rules == "Mastered")
3171 ruleType = TRuleType(TRuleType::rt_strict);
3174 TRaceFilter raceFilter;
3175 if(races["fyros"])
3176 raceFilter.setEnumValue(TRaceFilterEnum::rf_fyros);
3177 if(races["matis"])
3178 raceFilter.setEnumValue(TRaceFilterEnum::rf_matis);
3179 if(races["tryker"])
3180 raceFilter.setEnumValue(TRaceFilterEnum::rf_tryker);
3181 if(races["zorai"])
3182 raceFilter.setEnumValue(TRaceFilterEnum::rf_zorai);
3184 TReligionFilter religionFilter;
3185 if(religions["kami"])
3186 religionFilter.setEnumValue(TReligionFilterEnum::rf_kami);
3187 if(religions["karavan"])
3188 religionFilter.setEnumValue(TReligionFilterEnum::rf_karavan);
3189 if(religions["neutral"])
3190 religionFilter.setEnumValue(TReligionFilterEnum::rf_neutral);
3192 TGuildFilter guildFilter(anyPlayer?TGuildFilter::gf_any_player:TGuildFilter::gf_only_my_guild);
3194 TShardFilter shardFilter;
3195 for (uint i = 0; i < shards.size(); ++i)
3197 if (shards[i]) shardFilter.setEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i));
3200 TLevelFilter levelFilter;
3201 if(levels["20"])
3202 levelFilter.setEnumValue(TLevelFilterEnum::lf_a);
3203 if(levels["50"])
3204 levelFilter.setEnumValue(TLevelFilterEnum::lf_b);
3205 if(levels["100"])
3206 levelFilter.setEnumValue(TLevelFilterEnum::lf_c);
3207 if(levels["150"])
3208 levelFilter.setEnumValue(TLevelFilterEnum::lf_d);
3209 if(levels["200"])
3210 levelFilter.setEnumValue(TLevelFilterEnum::lf_e);
3211 if(levels["250"])
3212 levelFilter.setEnumValue(TLevelFilterEnum::lf_f);
3214 uint32 charId = 0;
3215 if (!ClientCfg.Local)
3216 charId = (NetMngr.getLoginCookie().getUserId()<< 4) + (uint32) PlayerSelectedSlot;
3218 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
3220 if(R2::getEditor().getAccessMode() != R2::CEditor::AccessDM)
3222 bool noob = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IS_NEWBIE")->getValueBool();
3223 if (FreeTrial && noob && (nevraxScenario != "1" || trialAllowed != "1"))
3225 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3226 if (pVT != NULL)
3227 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3228 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3230 return;
3235 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
3237 if (launchScenarioFromRingAccessPoint)
3239 // hibernate Edit Session if active
3240 sessionBrowser.hibernateEditSession(charId);
3241 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3243 nlwarning("hibernateEditSession callback return false");
3248 // schedule session
3249 bool launchSuccess = true;
3250 sessionBrowser.scheduleSession(charId, TSessionType::st_anim,
3251 title, description, sessionLevel,
3252 /*TAccessType::at_public,*/ ruleType, TEstimatedDuration::et_medium, 0, TAnimMode::am_dm,
3253 raceFilter, religionFilter, guildFilter, shardFilter, levelFilter, lang, RSMGR::TSessionOrientation(scenarioType),
3254 !globalAccess, autoInvite);
3256 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_scheduleSessionResult")))
3258 if(sessionBrowser._LastScheduleSessionResult==0)
3260 // start session
3261 sessionBrowser.startSession(sessionBrowser._LastScheduleSessionCharId,
3262 sessionBrowser._LastScheduleSessionId);
3264 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3267 if (launchScenarioFromRingAccessPoint)
3269 if (!initialIsland.empty() && !initialEntryPoint.empty() && !initialSeason.empty())
3271 sessionBrowser.setSessionStartParams(charId, sessionBrowser._LastScheduleSessionId, initialIsland, initialEntryPoint, initialSeason);
3275 TSessionPartStatus sessionStatus;
3276 if(ruleType==TRuleType::rt_liberal)
3277 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_play_invited);
3278 else
3279 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_anim_invited);
3281 // invite player
3282 sessionBrowser.inviteCharacter(
3283 sessionBrowser._LastScheduleSessionCharId,
3284 sessionBrowser._LastScheduleSessionId,
3285 sessionBrowser._LastScheduleSessionCharId,
3286 sessionStatus.toString());
3288 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3290 // request session
3291 FarTP.requestFarTPToSession(sessionBrowser._LastScheduleSessionId, PlayerSelectedSlot, CFarTP::JoinSession,
3292 !R2::getEditor().isInitialized());
3294 else
3296 nlwarning("inviteCharacter callback return false");
3299 if (sessionBrowser._LastInvokeResult != 0)
3301 nlwarning("inviteCharacter callback use error values %d", sessionBrowser._LastInvokeResult);
3304 if(sessionBrowser._LastInvokeResult == 14)
3306 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3307 if (pVT != NULL)
3308 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3309 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3313 // invite team
3314 if(inviteTeam)
3316 for (uint i = 0 ; i < 8 ; ++i)
3318 uint32 val = NLGUI::CDBManager::getInstance()->getDbProp(NLMISC::toString("SERVER:GROUP:%d:NAME",i))->getValue32();
3319 if(val!=0)
3321 STRING_MANAGER::CStringManagerClient *pSMC = STRING_MANAGER::CStringManagerClient::instance();
3322 string res;
3323 if (pSMC->getString(val,res))
3325 string charName = CEntityCL::removeTitleAndShardFromName(res);
3326 sessionBrowser.inviteCharacterByName(sessionBrowser._LastScheduleSessionCharId, charName);
3328 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3330 nlwarning("inviteCharacterByName callback return false");
3333 if(sessionBrowser._LastInvokeResult == 14)
3335 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3336 if (pVT != NULL)
3337 pVT->setTextLocalized("uiRingWarningInviteFreeTrial", true);
3338 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3345 else
3347 nlwarning("startSession callback return false");
3348 launchSuccess = false;
3351 else if(sessionBrowser._LastScheduleSessionResult==10)
3353 pIM->messageBoxWithHelp(CI18N::get("uiRingWarningBanishedPlayer"));
3355 else
3357 launchSuccess=false;
3360 else
3362 nlwarning("scheduleSession callback return false");
3363 launchSuccess = false;
3366 if(!launchSuccess)
3368 pIM->messageBoxWithHelp(CI18N::get("uiRingLaunchScenarioError"));
3370 else
3372 scenarioWnd->setActive(false);
3375 else
3377 // update session
3378 sessionBrowser.updateSessionInfo(charId, sessionBrowser._LastScheduleSessionId, title, 0, description, sessionLevel,
3379 /*TAccessType::at_public, */TEstimatedDuration::et_medium, 0, raceFilter, religionFilter,
3380 guildFilter, shardFilter, levelFilter, !globalAccess, autoInvite, lang, RSMGR::TSessionOrientation(scenarioType));
3382 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3384 nlwarning("updateSessionInfo callback return false");
3385 pIM->messageBoxWithHelp(CI18N::get("uiRingUpdateScenarioFiltersError"));
3387 else
3389 scenarioWnd->setActive(false);
3394 REGISTER_ACTION_HANDLER (CAHLoadScenario, "load_scenario");
3397 // ***************************************************************************
3398 class CAHOpenRingSessions : public IActionHandler
3400 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3402 if(!R2::getEditor().isInitialized())
3404 CInterfaceManager *pIM = CInterfaceManager::getInstance();
3405 CInterfaceGroup* ringSessionsWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:ring_sessions"));
3406 if(!ringSessionsWnd) return;
3407 ringSessionsWnd->setActive(true);
3411 REGISTER_ACTION_HANDLER (CAHOpenRingSessions, "open_ring_sessions");
3413 // ***************************************************************************
3414 class CAHInitImportCharacter : public IActionHandler
3416 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3418 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3419 if (!list)
3421 nlwarning("element " GROUP_LIST_CHARACTER " not found probably bad outgame.xml");
3422 return;
3425 // retrieve saved files
3426 std::vector<string> savedCharacters;
3427 CPath::getPathContent("save/", false, false, true, savedCharacters);
3429 CInterfaceGroup *newLine;
3430 CInterfaceGroup *prevLine = NULL;
3432 for (uint i = 0; i < savedCharacters.size(); ++i)
3434 // search saved characters only
3435 if (testWildCard(CFile::getFilename(savedCharacters[i]), "character_*.save"))
3437 const std::string id = CFile::getFilenameWithoutExtension(savedCharacters[i]).substr(strlen("character_"));
3438 if (id.empty())
3439 continue;
3441 std::vector<pair<string, string>> params;
3442 params.clear();
3443 params.push_back(std::pair<string, string>("id", id));
3444 // adjust ref
3445 if (list->getNumGroup() > 0)
3446 params.push_back(std::pair<string, string>("posref", "BL TL"));
3448 newLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_import", GROUP_LIST_CHARACTER, params);
3449 if (newLine)
3451 CViewText *text = dynamic_cast<CViewText*>(newLine->getView("name"));
3452 if (text)
3453 text->setText(string(savedCharacters[i]));
3455 // first button is pushed
3456 CCtrlButton *button = dynamic_cast<CCtrlButton*>(newLine->getCtrl("but"));
3457 if (button && list->getNumGroup() == 0)
3458 button->setPushed(true);
3460 // add to the list now
3461 newLine->setParent(list);
3462 newLine->setParentSize(list);
3463 newLine->setParentPos(prevLine);
3465 list->addGroup(newLine);
3467 prevLine = newLine;
3471 // none case
3472 if (list->getNumGroup() == 0)
3473 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(3)");
3475 list->invalidateCoords();
3478 REGISTER_ACTION_HANDLER( CAHInitImportCharacter, "import_char_init" );
3480 // ***************************************************************************
3481 class CAHResetImportCharacter : public IActionHandler
3483 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3485 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3486 if (list)
3487 list->clearGroups();
3489 if (!ImportCharacter.empty())
3490 ImportCharacter = "";
3493 REGISTER_ACTION_HANDLER( CAHResetImportCharacter, "import_char_reset" );
3495 // ***************************************************************************
3496 class CAHSelectImportCharacter : public IActionHandler
3498 virtual void execute (CCtrlBase *pCaller, const std::string &Params)
3500 struct CUnpush : public CInterfaceElementVisitor
3502 CCtrlBase *Ref;
3503 virtual void visitCtrl(CCtrlBase *ctrl)
3505 if (ctrl == Ref) return;
3506 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(ctrl);
3507 if (but)
3509 but->setPushed(false);
3513 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3514 if (!list)
3515 return;
3517 // unselect
3518 if (Params.empty())
3520 CUnpush unpusher;
3521 unpusher.Ref = pCaller;
3522 list->visit(&unpusher);
3525 // now select
3526 std::string name;
3527 if (Params.empty())
3529 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pCaller);
3530 if (!pCB)
3531 return;
3533 std::string id = pCB->getId();
3534 id = id.substr(0, id.rfind(':'));
3536 if (!fromString(id.substr(id.rfind(':')+1, id.size()), name))
3537 return;
3539 pCB->setPushed(true);
3541 else
3542 if (!fromString(Params, name))
3543 return;
3545 ImportCharacter = "";
3546 // check filename and store
3547 if (CFile::fileExists(toString("save/character_%s.save", name.c_str())))
3548 ImportCharacter = name;
3551 REGISTER_ACTION_HANDLER( CAHSelectImportCharacter, "import_char_select" );
3553 // ***************************************************************************
3554 class CAHImportCharacter : public IActionHandler
3556 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3558 if (ImportCharacter.empty())
3559 return;
3561 if (!CFile::fileExists(toString("save/character_%s.save", ImportCharacter.c_str())))
3562 return;
3564 bool success = false;
3566 CIFile fd;
3567 CCharacterSummary CS;
3568 // use temporary file until close()
3569 if (fd.open(toString("save/character_%s.save", ImportCharacter.c_str())))
3573 CS.serial(fd);
3574 SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", CS);
3576 // validate import
3577 CDBManager::getInstance()->getDbProp("UI:TEMP:IMPORT")->setValue32(1);
3578 success = true;
3580 catch (const EStream &e)
3582 nlwarning(e.what());
3584 fd.close();
3586 else
3587 nlwarning("Failed to open file: save/character_%s.save", ImportCharacter.c_str());
3589 // user notification
3590 if (!success)
3591 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(2)");
3592 else
3593 CAHManager::getInstance()->runActionHandler("proc", NULL, "proc_charsel_create_new");
3596 REGISTER_ACTION_HANDLER( CAHImportCharacter, "import_char" );
3598 // ***************************************************************************
3599 class CAHExportCharacter : public IActionHandler
3601 virtual void execute (CCtrlBase * /* pCaller */, const std::string &Params)
3603 if (Params.empty())
3604 return;
3606 sint32 slot = -1;
3607 if (!fromString(getParam(Params, "slot"), slot))
3608 return;
3610 if (slot >= CharacterSummaries.size() || slot < 0)
3611 return;
3613 // retrieve infos
3614 CCharacterSummary &CS = CharacterSummaries[slot];
3615 if (CS.Name.empty())
3616 return;
3618 // extract name
3619 const std::string name = buildPlayerNameForSaveFile(CS.Name.toUtf8());
3621 COFile fd;
3622 bool success = false;
3623 // use temporary file until close()
3624 if (fd.open(toString("save/character_%s.save", name.c_str()), false, false, true))
3628 fd.serial(CS);
3629 fd.flush();
3630 // validate
3631 success = true;
3633 catch (const EStream &e)
3635 nlwarning(e.what());
3637 fd.close();
3639 else
3640 nlwarning("Failed to open file: save/character_%s.save", name.c_str());
3642 const uint8 val = (success == true) ? 0 : 1;
3643 // user notification
3644 CLuaManager::getInstance().executeLuaScript(toString("outgame:procCharselNotifaction(%i)", val));
3647 REGISTER_ACTION_HANDLER( CAHExportCharacter, "export_char" );