Fix css style order when using external css files
[ryzomcore.git] / ryzom / client / src / connection.cpp
blobd7eaa2969e407e7d5f421918b038227c41a93d49
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 // Setup full screen if we have to
199 UDriver::CMode mode;
200 Driver->getCurrentScreenMode(mode);
202 if (mode.Windowed)
204 uint32 width, height;
205 Driver->getWindowSize(width, height);
206 mode.Width = width;
207 mode.Height = height;
210 // don't allow sizes smaller than 1024x768
211 if (ClientCfg.Width < 1024) ClientCfg.Width = 1024;
212 if (ClientCfg.Height < 768) ClientCfg.Height = 768;
214 if (StereoDisplay)
215 StereoDisplayAttached = StereoDisplay->attachToDisplay();
217 if (!StereoDisplayAttached && (
218 (ClientCfg.Windowed != mode.Windowed) ||
219 (ClientCfg.Width != mode.Width) ||
220 (ClientCfg.Height != mode.Height)))
222 mode.Windowed = ClientCfg.Windowed;
223 mode.Depth = uint8(ClientCfg.Depth);
224 mode.Width = ClientCfg.Width;
225 mode.Height = ClientCfg.Height;
226 mode.Frequency = ClientCfg.Frequency;
227 setVideoMode(mode);
230 // And setup hardware mouse if we have to
231 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached);
232 SetMouseFreeLook ();
233 SetMouseCursor ();
234 SetMouseSpeed (ClientCfg.CursorSpeed);
235 SetMouseAcceleration (ClientCfg.CursorAcceleration);
237 // Restore user UI scaling
238 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
242 #define UI_VARIABLES_SCREEN_WEBSTART 8
245 // ***************************************************************************
246 // Called to reload the start test page in test browser mode
247 class CAHOnReloadTestPage: public IActionHandler
249 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
251 CInterfaceManager *pIM = CInterfaceManager::getInstance();
252 // need to reset password and current screen
253 CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
255 pGH->browse(ClientCfg.TestBrowserUrl.c_str());
259 REGISTER_ACTION_HANDLER (CAHOnReloadTestPage, "on_reload_test_page");
262 // ------------------------------------------------------------------------------------------------
263 void setOutGameFullScreen()
265 if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1)
267 if (StereoDisplayAttached)
268 StereoDisplay->detachFromDisplay();
269 StereoDisplayAttached = false;
271 InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached);
274 // Enable auto scaling in login window
275 CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
278 // ------------------------------------------------------------------------------------------------
279 class CSoundGlobalMenu
281 public:
282 CSoundGlobalMenu()
284 _MusicWantedAsync= false;
285 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
287 void reset();
288 void setMusic(const string &music, bool async);
289 void updateSound();
290 private:
291 string _MusicPlayed;
292 string _MusicWanted;
293 bool _MusicWantedAsync;
294 sint _NbFrameBeforeChange;
295 enum {NbFrameBeforeChangeMax= 10};
298 void CSoundGlobalMenu::reset()
300 _MusicPlayed.clear();
301 _MusicWanted.clear();
304 void CSoundGlobalMenu::updateSound()
306 // **** update the music played
307 // The first music played is the music played at loading, before select char
308 if (_MusicPlayed.empty())
309 _MusicPlayed = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
310 if (_MusicWanted.empty())
311 _MusicWanted = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
313 // because music is changed when the player select other race for instance,
314 // wait the 3D to load (stall some secs)
316 // if the wanted music is the same as the one currently playing, just continue playing
317 if(_MusicPlayed!=_MusicWanted)
319 // wait nbFrameBeforeChangeMax before actually changing the music
320 _NbFrameBeforeChange--;
321 if(_NbFrameBeforeChange<=0)
323 _MusicPlayed= _MusicWanted;
324 // play the music
325 if (SoundMngr != NULL)
326 SoundMngr->playMusic(_MusicPlayed, 500, _MusicWantedAsync, true, true);
331 // **** update mngr
332 if (SoundMngr != NULL)
333 SoundMngr->update();
336 void CSoundGlobalMenu::setMusic(const string &music, bool async)
338 _MusicWanted= toLowerAscii(music);
339 _MusicWantedAsync= async;
340 // reset the counter
341 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
343 static CSoundGlobalMenu SoundGlobalMenu;
346 // New version of the menu after the server connection
348 // If you add something in this function, check CFarTP,
349 // some kind of reinitialization might be useful over there.
350 // ------------------------------------------------------------------------------------------------
351 bool connection (const string &cookie, const string &fsaddr)
354 NLMISC::TTime connStart = ryzomGetLocalTime();
355 NLMISC::TTime connLast = connStart;
356 NLMISC::TTime connCurrent = connLast;
358 game_exit = false;
360 // set resolution from cfg after login
361 connectionRestoreVideoMode ();
363 // Preload continents
365 const string nmsg("Loading continents...");
366 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
367 ContinentMngr.preloadSheets();
369 connLast = connCurrent;
370 connCurrent = ryzomGetLocalTime();
371 nlinfo ("PROFILE: %d seconds (%d total) for Loading continents", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
374 if (!fsaddr.empty () && !cookie.empty ())
376 // it means that we have a nel_launcher values, so we are online
377 ClientCfg.Local = 0;
378 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
381 CInterfaceManager *pIM = CInterfaceManager::getInstance();
383 // If the Client is in in Local Mode -> init the Time and return.
384 if (ClientCfg.Local)
386 #ifdef ENABLE_INCOMING_MSG_RECORDER
387 NetMngr.init("", "");
388 // Set the impulse callback.
389 NetMngr.setImpulseCallback (impulseCallBack);
390 // Set the database.
391 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
392 // init the string manager cache.
393 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
394 #endif
395 return true;
398 ProgressBar.setFontFactor(1.0f);
400 // Init out game
401 setOutGameFullScreen();
403 string nmsg("Initializing outgame...");
404 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
405 pIM->initOutGame();
407 connLast = connCurrent;
408 connCurrent = ryzomGetLocalTime();
409 nlinfo ("PROFILE: %d seconds (%d total) for Initializing outgame", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
411 // Init user interface
412 nmsg = "Initializing user interface...";
413 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
415 // Hide cursor for interface
416 //Driver->showCursor (false);
418 // Init global variables
419 userChar = false;
420 noUserChar = false;
421 ConnectInterf = true;
422 CreateInterf = true;
423 CharacterInterf = true;
424 WaitServerAnswer= false;
426 FarTP.setOutgame();
428 // Start the finite state machine
429 static bool firstConnection = true;
430 TInterfaceState InterfaceState = AUTO_LOGIN;
431 // TInterfaceState InterfaceState = firstConnection ? AUTO_LOGIN : GLOBAL_MENU;
432 /*if (!firstConnection)
434 noUserChar = userChar = false;
435 WaitServerAnswer = true;
438 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(ClientCfg.Local ? 6 : -1); // TMP TMP
439 IngameDbMngr.flushObserverCalls();
440 NLGUI::CDBManager::getInstance()->flushObserverCalls();
442 // Active inputs
443 Actions.enable(true);
444 EditActions.enable(true);
446 if (ClientCfg.SelectCharacter == -1)
448 // not initialized at login and remain hardware until here ...
450 // Re-initialise the mouse (will be now in hardware mode, if required)
451 //InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
453 // no ui init if character selection is automatic
454 //SetMouseFreeLook ();
455 //SetMouseCursor ();
456 SetMouseSpeed (ClientCfg.CursorSpeed);
457 SetMouseAcceleration (ClientCfg.CursorAcceleration);
459 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
460 PlayerSelectedSlot = ClientCfg.SelectedSlot;
463 connLast = connCurrent;
464 connCurrent = ryzomGetLocalTime();
465 nlinfo ("PROFILE: %d seconds (%d total) for Initializing user interface", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
467 nlinfo ("PROFILE: %d seconds for connection", (uint32)(ryzomGetLocalTime ()-connStart)/1000);
469 // Init web box
471 // TMP TMP
472 if (ClientCfg.Local)
474 InterfaceState = GLOBAL_MENU;
477 // No loading music here, this is right before character selection, using the existing music
479 // Create the loading texture. We can't do that before because we need to add search path first.
480 beginLoading (LoadBackground);
481 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
483 while ((InterfaceState != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
485 switch (InterfaceState)
487 case AUTO_LOGIN:
488 InterfaceState = autoLogin (cookie, fsaddr, firstConnection);
489 break;
491 case GLOBAL_MENU:
492 if (!ClientCfg.Local)
494 if (ClientCfg.SelectCharacter == -1)
496 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
499 InterfaceState = globalMenu();
500 break;
501 case GOGOGO_IN_THE_GAME:
502 break;
503 case QUIT_THE_GAME:
504 break;
508 firstConnection = false;
510 // Restore user UI scaling
511 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
513 // Disable inputs
514 Actions.enable(false);
515 EditActions.enable(false);
517 // resetTextContext ("ingame.ttf", true);
518 resetTextContext ("ryzom.ttf", true);
520 if (InterfaceState == GOGOGO_IN_THE_GAME)
522 // set background downloader to 'paused' to ease loading of client
523 #ifdef RYZOM_BG_DOWNLOADER
524 pauseBGDownloader();
525 #endif
526 return true;
529 if (InterfaceState == QUIT_THE_GAME)
530 return false;
531 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
532 return true;
538 // Allow user to reselect character after the server reconnection
539 // ------------------------------------------------------------------------------------------------
540 bool reconnection()
543 game_exit = false;
545 setOutGameFullScreen();
547 // Preload continents
549 const string nmsg ("Loading continents...");
550 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
551 ContinentMngr.preloadSheets();
554 if (!fsaddr.empty () && !cookie.empty ())
556 // it means that we have a nel_launcher values, so we are online
557 ClientCfg.Local = 0;
558 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
561 // If the Client is in in Local Mode -> init the Time and return.
562 if (ClientCfg.Local)
564 #ifdef ENABLE_INCOMING_MSG_RECORDER
565 NetMngr.init("", "");
566 // Set the impulse callback.
567 NetMngr.setImpulseCallback (impulseCallBack);
568 // Set the database.
569 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
570 // init the string manager cache.
571 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
572 #endif
573 connectionRestoreVideoMode ();
574 return true;
578 CInterfaceManager *pIM = CInterfaceManager::getInstance();
580 ProgressBar.setFontFactor(1.0f);
582 // Init out game
583 SoundGlobalMenu.reset();
584 pIM->initOutGame();
586 // Hide cursor for interface
587 Driver->showCursor (false);
589 // Init global variables
590 userChar = false;
591 noUserChar = false;
592 ConnectInterf = true;
593 CreateInterf = true;
594 CharacterInterf = true;
595 WaitServerAnswer= false;
597 FarTP.setOutgame();
599 if (SoundMngr)
600 SoundMngr->setupFadeSound(1.0f, 1.0f);
602 // these two globals sequence GlobalMenu to display the character select dialog
603 WaitServerAnswer = true;
604 userChar = true;
606 // Start the finite state machine
607 TInterfaceState InterfaceState = GLOBAL_MENU;
609 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(-1);
610 IngameDbMngr.flushObserverCalls();
611 NLGUI::CDBManager::getInstance()->flushObserverCalls();
613 // Active inputs
614 Actions.enable(true);
615 EditActions.enable(true);
617 if (ClientCfg.SelectCharacter == -1)
619 // Re-initialise the mouse (will be now in hardware mode, if required)
620 SetMousePosFirstTime = true;
621 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
623 // no ui init if character selection is automatic
624 SetMouseFreeLook ();
625 SetMouseCursor ();
626 SetMouseSpeed (ClientCfg.CursorSpeed);
627 SetMouseAcceleration (ClientCfg.CursorAcceleration);
628 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
629 PlayerSelectedSlot = ClientCfg.SelectedSlot;
632 // we want the teleport graphics to display (not like in Server Hop mode)
633 // this also kicks the state machine to sendReady() so we stop spinning in farTPmainLoop
634 FarTP.setIngame();
636 // Not loading music here, this is before character selection, keep existing music
638 // Create the loading texture. We can't do that before because we need to add search path first.
639 beginLoading (LoadBackground);
640 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
642 // character selection menu
643 while( InterfaceState == GLOBAL_MENU ) // != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
645 if (ClientCfg.SelectCharacter == -1)
647 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
649 InterfaceState = globalMenu();
652 // Restore user UI scaling
653 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
655 // Disable inputs
656 Actions.enable(false);
657 EditActions.enable(false);
659 // resetTextContext ("ingame.ttf", true);
660 resetTextContext ("ryzom.ttf", true);
662 if (InterfaceState == GOGOGO_IN_THE_GAME)
664 #ifdef RYZOM_BG_DOWNLOADER
665 pauseBGDownloader();
666 #endif
667 return true;
669 if (InterfaceState == QUIT_THE_GAME)
670 return false;
671 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
672 return true;
675 // Automatic connection to the server, the user can't do anything
676 // ------------------------------------------------------------------------------------------------
677 TInterfaceState autoLogin (const string &cookie, const string &fsaddr, bool firstConnection)
679 noUserChar = userChar = false;
680 string defaultPort = string(":47851");
681 if(!fsaddr.empty())
683 // If we have a front end address from command line, use this one
684 UsedFSAddr = fsaddr;
685 if (UsedFSAddr.find(":") == string::npos)
687 UsedFSAddr += defaultPort;
690 else
692 // Otherwise, use the front end address from configfile
693 UsedFSAddr = ClientCfg.FSHost;
694 FSAddr = UsedFSAddr; // to be able to do /reconnect
695 LoginSM.pushEvent( CLoginStateMachine::ev_skip_all_login );
696 if (UsedFSAddr.find(":") == string::npos)
698 UsedFSAddr += defaultPort;
699 FSAddr += defaultPort; // to be able to do /reconnect
703 if (firstConnection)
704 NetMngr.init (cookie, UsedFSAddr);
706 // Connection
707 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
709 string result;
711 if (firstConnection)
713 NetMngr.connect (result);
715 if (!result.empty())
717 nlerror ("connection : %s.", result.c_str());
718 return QUIT_THE_GAME;
721 // Ok the client is connected
723 // Set the impulse callback.
724 NetMngr.setImpulseCallback (impulseCallBack);
725 // Set the database.
726 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
728 // init the string manager cache.
729 STRING_MANAGER::CStringManagerClient::instance()->initCache(UsedFSAddr, ClientCfg.LanguageCode);
732 else
734 CCharacterSummary cs;
735 cs.Name = "babar";
736 //cs.Surname = "l'elephant";
737 cs.People = EGSPD::CPeople::Zorai;
738 cs.VisualPropA.PropertySubData.Sex = 0; // Male
739 //Deprecated
740 // cs.Role = ROLES::range_warrior;
741 // cs.Job = JOBS::CasterBuffer;
742 // cs.JobLevel = 16;
743 CharacterSummaries.push_back(cs);
745 cs.Name = "yeah";
746 //cs.Surname = "zeelot";
747 cs.People = EGSPD::CPeople::Matis;
748 cs.VisualPropA.PropertySubData.Sex = 1; // Female
749 //Deprecated
750 // cs.Role = ROLES::buffer_magician;
751 // cs.Job = JOBS::CasterHealer;
752 // cs.JobLevel = 8;
753 CharacterSummaries.push_back(cs);
755 userChar = true;
758 WaitServerAnswer = true;
760 return GLOBAL_MENU;
763 // ------------------------------------------------------------------------------------------------
764 void globalMenuMovieShooter()
767 if(MovieShooterSaving)
769 // Add the buffer frame to the movie.
770 if(!MovieShooter.addFrame(TimeInSec, Driver))
772 // Fail to add the frame => abort.
773 endMovieShooting();
775 else
777 // Ok, just add a display.
778 displaySpecialTextProgress("MovieShooting");
784 // ------------------------------------------------------------------------------------------------
785 // Build a valid PlayerName for file Save selection.
786 std::string buildPlayerNameForSaveFile(const std::string &playerNameIn)
788 // remove any shard name appended
789 string playerName = playerNameIn;
790 string::size_type pos = playerNameIn.find('(');
791 if(pos!=string::npos && pos>0)
793 playerName.resize(pos);
796 // replace any special ucchar with '_'
797 string ret;
798 ret.resize(playerName.size());
799 for(uint i=0;i<playerName.size();i++)
801 ucchar c= playerName[i];
802 if( (c>='A' && c<='Z') ||
803 (c>='a' && c<='z') ||
804 (c>='0' && c<='9') ||
805 (c=='_') )
807 ret[i]= tolower(c); // TODO: toLowerAscii
809 else
810 ret[i]= '_';
812 return ret;
816 #ifdef RYZOM_BG_DOWNLOADER
817 static bool LuaBGDSuccessFlag = true; // tmp, for debug
819 void updateBGDownloaderUI()
821 CInterfaceManager *im = CInterfaceManager::getInstance();
822 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
823 bool bgWindowVisible = true;
824 if (im->isInGame())
826 static NLMISC::CRefPtr<CInterfaceElement> bgDownloaderWindow;
827 if (!bgDownloaderWindow)
829 bgDownloaderWindow = CWidgetManager::getInstance()->getElementFromId("ui:interface:bg_downloader");
831 bgWindowVisible = bgDownloaderWindow && bgDownloaderWindow->getActive();
833 bool prevSuccess = LuaBGDSuccessFlag;
834 if (isBGDownloadEnabled() && PatchBegun)
836 if (AvailablePatchs == 0)
838 if (LuaBGDSuccessFlag)
840 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
843 else
845 switch(bgDownloader.getLastTaskResult())
847 case BGDownloader::TaskResult_Unknown:
849 float progress = 0.f;
850 /*if (bgDownloader.getTotalSize() != 0)
852 progress = (float) bgDownloader.getPatchingSize() / bgDownloader.getTotalSize();
854 if (bgDownloader.getTotalFilesToGet() != 0)
856 progress = (bgDownloader.getCurrentFilesToGet() + bgDownloader.getCurrentFileProgress()) / bgDownloader.getTotalFilesToGet();
858 if (LuaBGDSuccessFlag && bgWindowVisible)
860 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript(toString("bgdownloader:setPatchProgress(%f)", progress));
862 // display current priority of the downloader
863 if (LuaBGDSuccessFlag && bgWindowVisible)
865 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:displayPriority()");
868 break;
869 case BGDownloader::TaskResult_Success:
870 if (LuaBGDSuccessFlag && bgWindowVisible)
872 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
874 // task finished
875 AvailablePatchs = 0;
876 if (bgDownloader.getPatchCompletionFlag(true /* clear flag */))
878 // when in-game, display a message to signal the end of the patch
879 if (im->isInGame())
881 im->displaySystemInfo(CI18N::get("uiBGD_InGamePatchCompletion"), "BC");
884 break;
885 default:
886 // error case
887 if (LuaBGDSuccessFlag && bgWindowVisible)
889 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchError()");
891 break;
895 else
897 if (LuaBGDSuccessFlag && bgWindowVisible)
899 if (isBGDownloadEnabled())
901 // no necessary patch for now
902 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoNecessaryPatch()");
904 else
906 // no download ui
907 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoDownloader()");
911 if (prevSuccess != LuaBGDSuccessFlag)
913 nlwarning("Some scipt error occurred");
916 #endif
918 // compute patcher priority, depending on the presence of one or more mainland characters : in this case, give the patch a boost
919 void updatePatcherPriorityBasedOnCharacters()
921 #ifdef RYZOM_BG_DOWNLOADER
922 if (isBGDownloadEnabled())
924 if (CBGDownloaderAccess::getInstance().getDownloadThreadPriority() != BGDownloader::ThreadPriority_Paused)
926 // choose priority based on available characters :
927 bool hasMainlandChar = false;
928 for(std::vector<CCharacterSummary>::iterator it = CharacterSummaries.begin(); it != CharacterSummaries.end(); ++it)
930 if (it->Name.empty()) continue;
931 if (!it->InNewbieland)
933 hasMainlandChar = true;
934 break;
937 CBGDownloaderAccess::getInstance().requestDownloadThreadPriority(hasMainlandChar ? BGDownloader::ThreadPriority_Normal : BGDownloader::ThreadPriority_Low, false);
940 #endif
943 // Launch the interface to choose a character
944 // ------------------------------------------------------------------------------------------------
945 TInterfaceState globalMenu()
947 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_CharacterSelection, "login_step_character_selection"));
949 #ifdef RYZOM_BG_DOWNLOADER
950 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
952 if (isBGDownloadEnabled())
954 // If there's a need for mainland download, then proceed
955 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
957 // if a task is already started, then this was a situation where player went back from game to the character selection,
958 // so just unpause
959 BGDownloader::TTaskResult dummyResult;
960 ucstring dummyMessage; // OLD
961 if (!bgDownloader.isTaskEnded(dummyResult, dummyMessage))
963 unpauseBGDownloader();
967 #endif
969 CInterfaceManager *pIM = CInterfaceManager::getInstance();
971 sint32 nScreenConnecting, nScreenIntro, nScreenServerCrashed;
972 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_connecting"), nScreenConnecting);
973 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_intro"), nScreenIntro);
974 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_crashing"), nScreenServerCrashed);
976 // SKIP INTRO : Write to the database if we have to skip the intro and write we want to skip further intro to client cfg
977 if (ClientCfg.SkipIntro)
979 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:SKIP_INTRO", false);
980 if (pNL != NULL)
981 pNL->setValue64(1);
984 TGameCycle serverTick = NetMngr.getCurrentServerTick();
985 bool PlayerWantToGoInGame = false;
986 bool firewallTimeout = false;
988 ProgressBar.finish(); // no progress while selecting character
990 while (PlayerWantToGoInGame == false)
993 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
994 // tmp for debug
995 if (::GetAsyncKeyState(VK_SPACE))
997 pIM->uninitOutGame();
998 pIM->initOutGame();
999 CWidgetManager::getInstance()->activateMasterGroup ("ui:outgame", true);
1000 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(2); // TMP TMP
1001 IngameDbMngr.flushObserverCalls();
1002 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1003 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(false);
1004 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(true);
1005 // Active inputs
1006 Actions.enable(true);
1007 EditActions.enable(true);
1008 LuaBGDSuccessFlag = true;
1009 CWidgetManager::getInstance()->getParser()->reloadAllLuaFileScripts();
1011 #endif
1013 #ifdef RYZOM_BG_DOWNLOADER
1014 updateBGDownloaderUI();
1015 #endif
1017 // Update network.
1020 if ( ! firewallTimeout )
1021 NetMngr.update();
1023 catch (const EBlockedByFirewall&)
1025 if ( NetMngr.getConnectionState() == CNetManager::Disconnect )
1027 firewallTimeout = true;
1029 else
1031 // Display the firewall alert string
1032 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:connecting:title"));
1033 if (pVT != NULL)
1034 pVT->setTextLocalized("uiFirewallAlert", true);
1036 // The mouse and fullscreen mode should be unlocked for the user to set the firewall permission
1037 nlSleep( 30 ); // 'nice' the client, and prevent to make too many send attempts
1041 IngameDbMngr.flushObserverCalls();
1042 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1044 // check if we can send another dated block
1045 if (NetMngr.getCurrentServerTick() != serverTick)
1048 serverTick = NetMngr.getCurrentServerTick();
1049 NetMngr.send(serverTick);
1051 else
1053 // Send dummy info
1054 NetMngr.send();
1056 // Update the DT T0 and T1 global variables
1057 updateClientTime();
1058 CInputHandlerManager::getInstance()->pumpEvents();
1059 Driver->clearBuffers(CRGBA::Black);
1060 Driver->setMatrixMode2D11();
1062 // Update sound
1063 SoundGlobalMenu.updateSound();
1065 // Interface handling & displaying (processes clicks...)
1066 pIM->updateFrameEvents();
1067 pIM->updateFrameViews(NULL);
1068 IngameDbMngr.flushObserverCalls();
1069 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1071 // Movie shooter
1072 globalMenuMovieShooter();
1074 // Force the client to sleep a bit.
1075 if(ClientCfg.Sleep >= 0)
1077 nlSleep(ClientCfg.Sleep);
1080 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
1081 if (::GetAsyncKeyState(VK_CONTROL))
1083 pIM->displayUIViewBBoxs("");
1084 pIM->displayUICtrlBBoxs("");
1085 pIM->displayUIGroupBBoxs("");
1086 displayDebugUIUnderMouse();
1088 #endif
1090 // Display
1091 Driver->swapBuffers();
1093 // SERVER INTERACTIONS WITH INTERFACE
1094 if (WaitServerAnswer)
1096 if (noUserChar || userChar)
1098 #ifdef RYZOM_BG_DOWNLOADER
1099 if (isBGDownloadEnabled())
1101 // If there's a need for mainland download, then proceed
1102 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
1104 // if a task is already started, then this was a situation where player went back from game to the character selection,
1105 // so just unpause
1106 BGDownloader::TTaskResult dummyResult;
1107 ucstring dummyMessage; // OLD
1108 if (bgDownloader.isTaskEnded(dummyResult, dummyMessage))
1110 // launch mainland patch as a background task
1111 BGDownloader::CTaskDesc task(BGDownloader::DLState_GetAndApplyPatch,
1112 (1 << BGDownloader::DownloadID_MainLand));
1113 bgDownloader.startTask(task, getBGDownloaderCommandLine(), false /* showDownloader */);
1115 // choose priority based on available characters :
1116 updatePatcherPriorityBasedOnCharacters();
1118 PatchBegun = true;
1122 #endif
1124 //nlinfo("impulseCallBack : received userChars list");
1125 noUserChar = userChar = false;
1126 if( FarTP.isReselectingChar() || !FarTP.isServerHopInProgress() ) // if doing a Server Hop, expect serverReceivedReady without action from the user
1128 sint charSelect = -1;
1129 if (ClientCfg.SelectCharacter != -1)
1130 charSelect = ClientCfg.SelectCharacter;
1132 if (LoginCharsel != -1)
1133 charSelect = LoginCharsel;
1135 WaitServerAnswer = false;
1136 if (charSelect == -1)
1138 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_CHARS", false);
1139 if (pNL != NULL)
1141 pNL->setValue64 (1); // Send impulse to interface observers
1142 IngameDbMngr.flushObserverCalls();
1143 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1144 pNL->setValue64 (0);
1145 IngameDbMngr.flushObserverCalls();
1146 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1149 else
1151 // check that the pre selected character is available
1152 if (CharacterSummaries[charSelect].People == EGSPD::CPeople::Unknown || charSelect > 4)
1154 // BAD ! preselected char does not exist, use the first available or fail
1155 uint i;
1156 for (i=0; i<CharacterSummaries.size(); ++i)
1158 if (CharacterSummaries[i].People != EGSPD::CPeople::Unknown)
1159 break;
1161 if (i == CharacterSummaries.size())
1163 Driver->systemMessageBox("You have no character for the current user.\nClient will exit.", "Char loading error", UDriver::okType, UDriver::exclamationIcon);
1164 exit(-1);
1166 else
1168 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);
1169 if (ret == UDriver::noId)
1170 exit(-1);
1171 else
1172 charSelect = i;
1175 // Auto-selection for fast launching (dev only)
1176 CAHManager::getInstance()->runActionHandler("launch_game", NULL, toString("slot=%d|edit_mode=0", charSelect));
1178 if (LoginCharsel == -1)
1179 ClientCfg.SelectCharacter = charSelect;
1184 // Clear sending buffer that may contain prevous QUIT_GAME when getting back to the char selection screen
1185 NetMngr.flushSendBuffer();
1188 if (CharNameValidArrived)
1190 //nlinfo("impulseCallBack : received CharNameValidArrived");
1191 CharNameValidArrived = false;
1192 WaitServerAnswer = false;
1193 if (ClientCfg.SelectCharacter == -1)
1195 CCDBNodeLeaf *pNL;
1196 pNL = NLGUI::CDBManager::getInstance()->getDbProp(CharNameValidDBLink,false);
1197 if (pNL != NULL)
1199 if (CharNameValid)
1200 pNL->setValue64(1);
1201 else
1202 pNL->setValue64(0);
1205 pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_VALID", false);
1206 if (pNL != NULL)
1208 pNL->setValue64 (1); // Send impulse to interface observers
1209 IngameDbMngr.flushObserverCalls();
1210 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1211 pNL->setValue64 (0);
1212 IngameDbMngr.flushObserverCalls();
1213 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1218 if (serverReceivedReady)
1220 //nlinfo("impulseCallBack : received serverReceivedReady");
1221 serverReceivedReady = false;
1222 WaitServerAnswer = false;
1223 PlayerWantToGoInGame = true;
1226 else
1228 noUserChar = false;
1229 userChar = false;
1230 CharNameValidArrived = false;
1231 serverReceivedReady = false;
1234 // Check if server disconnect the client
1235 if (!ClientCfg.Local)
1237 if (NetMngr.getConnectionState() == CNetManager::Disconnect)
1239 // Display the connection failure screen
1240 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:CURRENT_SCREEN", false);
1241 if (pNL != NULL)
1242 pNL->setValue64 (nScreenServerCrashed);
1244 if ( firewallTimeout )
1246 // Display the firewall error string instead of the normal failure string
1247 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:crashing:title"));
1248 if (pVT != NULL)
1250 pVT->setMultiLine( true );
1251 pVT->setTextLocalized(CI18N::get("uiFirewallFail")+".\n"+
1252 CI18N::get("uiFirewallAlert")+".", false);
1260 // We want to quit the game without playing
1261 if (game_exit)
1262 return QUIT_THE_GAME;
1265 if (ClientCfg.SelectCharacter != -1)
1266 PlayerSelectedSlot = ClientCfg.SelectCharacter;
1268 // Notify the state machine that we're exiting from global menu
1269 LoginSM.pushEvent(CLoginStateMachine::ev_global_menu_exited);
1271 // Init the current Player Name (for interface.cfg and sentence.name save). Make a good File Name.
1272 string playerName = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1273 PlayerSelectedFileName = buildPlayerNameForSaveFile(playerName);
1275 // Init the current Player Home shard Id and name
1276 CharacterHomeSessionId = CharacterSummaries[PlayerSelectedSlot].Mainland;
1277 PlayerSelectedMainland= CharacterSummaries[PlayerSelectedSlot].Mainland;
1278 PlayerSelectedHomeShardName.clear();
1279 PlayerSelectedHomeShardNameWithParenthesis.clear();
1280 for(uint i=0;i<CShardNames::getInstance().getSessionNames().size();i++)
1282 const CShardNames::TSessionName &sessionName= CShardNames::getInstance().getSessionNames()[i];
1283 if(PlayerSelectedMainland == sessionName.SessionId)
1285 PlayerSelectedHomeShardName= sessionName.DisplayName;
1286 PlayerSelectedHomeShardNameWithParenthesis= '(' + PlayerSelectedHomeShardName + ')';
1291 // Restore video mode
1292 if (ClientCfg.SelectCharacter == -1)
1294 if (ClientCfg.Windowed)
1296 // if used changed window resolution in char select
1297 // if we don't update ClientCfg, then UI from icfg is restored wrong
1298 uint32 width, height;
1299 Driver->getWindowSize(width, height);
1300 ClientCfg.Width = width;
1301 ClientCfg.Height = height;
1304 connectionRestoreVideoMode ();
1307 // Skip intro next time
1308 ClientCfg.writeBool("SkipIntro", true);
1310 // return SELECT_CHARACTER;
1311 return GOGOGO_IN_THE_GAME;
1315 // Init the character selection slot texts from the character summaries
1316 // ------------------------------------------------------------------------------------------------
1317 class CAHNetInitCharSel : public IActionHandler
1319 public:
1320 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1322 string sPath = getParam(Params, "slottexts");
1323 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1324 uint i;
1325 for (i = 0; i < CharacterSummaries.size(); ++i)
1327 CCharacterSummary &rCS = CharacterSummaries[i];
1328 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i));
1329 CViewText *pVT = dynamic_cast<CViewText*>(pIE);
1330 if (pVT == NULL) return;
1332 if (rCS.Name.empty())
1333 pVT->setTextLocalized("uiEmptySlot", true);
1334 else
1335 pVT->setTextLocalized(rCS.Name.toUtf8(), false);
1337 // 5 slots
1338 for (; i < 5; ++i)
1340 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i)));
1341 if (pVT == NULL) return;
1342 pVT->setTextLocalized("uiEmptySlot", true);
1346 REGISTER_ACTION_HANDLER (CAHNetInitCharSel, "net_init_char_sel");
1348 // ------------------------------------------------------------------------------------------------
1349 void setTarget(CCtrlBase *ctrl, const string &targetName, std::string &value)
1351 std::vector<CInterfaceLink::CTargetInfo> targets;
1352 // find first enclosing group
1353 CCtrlBase *currCtrl = ctrl;
1354 CInterfaceGroup *ig = NULL;
1355 while (currCtrl)
1357 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1358 if (ig != NULL) break;
1359 currCtrl = currCtrl->getParent();
1361 if (ig)
1363 CInterfaceExprValue exprValue;
1364 exprValue.setString(value);
1366 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1367 for(uint k = 0; k < targets.size(); ++k)
1369 if (targets[k].Elem) targets[k].affect(exprValue);
1374 // ------------------------------------------------------------------------------------------------
1375 void setTarget(CCtrlBase *ctrl, const string &targetName, uint32 value)
1377 std::vector<CInterfaceLink::CTargetInfo> targets;
1378 // find first enclosing group
1379 CCtrlBase *currCtrl = ctrl;
1380 CInterfaceGroup *ig = NULL;
1381 while (currCtrl)
1383 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1384 if (ig != NULL) break;
1385 currCtrl = currCtrl->getParent();
1387 if (ig)
1389 CInterfaceExprValue exprValue;
1390 exprValue.setInteger(value);
1392 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1393 for(uint k = 0; k < targets.size(); ++k)
1395 if (targets[k].Elem) targets[k].affect(exprValue);
1400 // ------------------------------------------------------------------------------------------------
1401 class CAHGetSlot: public IActionHandler
1403 public:
1404 virtual void execute (CCtrlBase *pCaller, const string &Params)
1406 string sProp = getParam(Params, "prop");
1407 string sTarget = getParam(Params, "target");
1408 string sSlot = getParam(Params, "slot");
1410 CInterfaceExprValue result;
1411 if (!CInterfaceExpr::eval(sSlot, result))
1412 return;
1413 uint8 selectedSlot = (uint8)result.getInteger();
1414 if (selectedSlot >= CharacterSummaries.size())
1415 return;
1417 PlayerSelectedSlot = selectedSlot;
1419 if (CharacterSummaries[PlayerSelectedSlot].Name.empty())
1420 return;
1422 string sValue;
1423 uint32 nValue = 0;
1425 if (sProp == "name")
1427 sValue = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1428 setTarget (pCaller, sTarget, sValue);
1430 /* else if (sProp == "surname")
1431 Deprecated {
1432 sValue = CharacterSummaries[PlayerSelectedSlot].Surname;
1433 setTarget (pCaller, sTarget, sValue);
1435 */ else if (sProp == "title")
1437 bool womanTitle;
1438 if( CharacterSummaries[PlayerSelectedSlot].VisualPropA.PropertySubData.Sex == 1 )
1440 UserEntity->setGender( GSGENDER::female );
1441 womanTitle = true;
1443 else
1445 UserEntity->setGender( GSGENDER::male );
1446 womanTitle = false;
1448 string titleStr = CHARACTER_TITLE::toString(CharacterSummaries[PlayerSelectedSlot].Title);
1449 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(titleStr, womanTitle);
1451 // Sometimes translation contains another title
1452 string::size_type pos = sValue.find('$');
1453 if (pos != string::npos)
1455 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sValue), womanTitle);
1458 setTarget (pCaller, sTarget, sValue);
1460 /* else if (sProp == "orient")
1461 Deprecated {
1462 sValue = ROLES::roleToUCString(CharacterSummaries[PlayerSelectedSlot].Role);
1463 setTarget (pCaller, sTarget, sValue);
1465 else if (sProp == "job")
1467 //Deprecated
1468 // sValue = JOBS::jobToUCString(CharacterSummaries[PlayerSelectedSlot].Job);
1469 sValue = JOBS::jobToUCString(JOBS::BladeBearer);
1470 setTarget (pCaller, sTarget, sValue);
1472 */ else if (sProp == "level")
1474 //Deprecated
1475 // sValue = toString(CharacterSummaries[PlayerSelectedSlot].JobLevel);
1476 sValue = toString(1);
1477 setTarget (pCaller, sTarget, sValue);
1479 else if (sProp == "pos")
1481 nValue = CharacterSummaries[PlayerSelectedSlot].Location;
1482 setTarget (pCaller, sTarget, nValue);
1486 REGISTER_ACTION_HANDLER (CAHGetSlot, "get_slot");
1489 // Setup the database from a database entry which represents a slot
1490 // ------------------------------------------------------------------------------------------------
1491 class CAHSetDBFromSlot : public IActionHandler
1493 public:
1494 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1496 string sDBLink = getParam(Params, "dblink");
1497 string sSlot = getParam(Params, "slot");
1499 CInterfaceExprValue result;
1500 if (!CInterfaceExpr::eval(sSlot, result))
1501 return;
1503 PlayerSelectedSlot = (uint8)result.getInteger();
1505 if (PlayerSelectedSlot >= CharacterSummaries.size())
1506 return;
1508 // Setup the database from the character summary
1509 CCharacterSummary &rCS = CharacterSummaries[PlayerSelectedSlot];
1510 if (rCS.Name.empty())
1511 return;
1513 SCharacter3DSetup::setupDBFromCharacterSummary(sDBLink, rCS);
1516 REGISTER_ACTION_HANDLER (CAHSetDBFromSlot, "set_db_from_slot");
1519 // Reset all the pushed radio button of a group
1520 // ------------------------------------------------------------------------------------------------
1521 class CAHResetPushed: public IActionHandler
1523 public:
1524 virtual void execute (CCtrlBase *pCaller, const string &Params)
1526 string sDBLink = getParam(Params, "dblink");
1527 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1528 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(pCaller->getId(), sDBLink);
1529 CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup*>(pIE);
1530 if (pIG == NULL) return;
1532 const vector<CCtrlBase*> vCB = pIG->getControls();
1533 for (uint i = 0; i < vCB.size(); ++i)
1535 CCtrlBaseButton *pBut = dynamic_cast<CCtrlBaseButton*>(vCB[i]);
1536 if (pBut && pBut->getType() == CCtrlBaseButton::RadioButton)
1538 pBut->setPushed (false);
1543 REGISTER_ACTION_HANDLER (CAHResetPushed, "reset_pushed");
1549 // Launch the game given a slot (slot is reference to the character summaries
1550 // ------------------------------------------------------------------------------------------------
1551 class CAHLaunchGame : public IActionHandler
1553 public:
1554 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1556 // Get the edit/play mode
1557 string sEditMode = getParam(Params, "edit_mode");
1558 bool wantsEditMode = false;
1559 CInterfaceExprValue result;
1560 bool wantsNewScenario = false;
1562 if (CInterfaceExpr::eval(sEditMode, result))
1564 wantsEditMode = (result.getInteger() == 1) || (result.getInteger() == 2);
1565 wantsNewScenario = (result.getInteger() == 2);
1568 CInterfaceManager *im = CInterfaceManager::getInstance();
1569 if (wantsEditMode)
1571 // full patch needed for edition, warn the client
1572 if (AvailablePatchs != 0)
1574 if (im->isInGame())
1576 inGamePatchUncompleteWarning();
1578 else
1580 im->messageBoxWithHelp(CI18N::get("uiBGD_FullPatchNeeded"), "ui:outgame");
1582 return;
1586 // Get the player selected slot
1587 string sSlot = getParam(Params, "slot");
1588 if (sSlot != "ingame_auto")
1590 CInterfaceExprValue result;
1591 if (!CInterfaceExpr::eval(sSlot, result))
1592 return;
1593 PlayerSelectedSlot = (uint8)result.getInteger();
1594 if (PlayerSelectedSlot >= CharacterSummaries.size())
1595 return;
1597 ClientCfg.writeInt("SelectedSlot",PlayerSelectedSlot);
1598 if (ClientCfg.SaveConfig)
1599 ClientCfg.ConfigFile.save();
1604 static volatile bool isMainlandCharacter = false; // TMP until we can get this info
1605 if (isMainlandCharacter)
1607 nlassert(0); // use id="message_box" !!!
1608 if (AvailablePatchs != 0)
1610 im->messageBoxWithHelp(CI18N::get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame");
1612 return;
1617 // Select the right sheet to create the user character.
1618 ClientCfg.UserSheet = CharacterSummaries[PlayerSelectedSlot].SheetId.toString();
1620 // If the user wants to enter its editing session, get the ring server to Far TP to.
1621 if (wantsEditMode)
1624 if (wantsNewScenario)
1626 CSessionBrowserImpl &sb = CSessionBrowserImpl::getInstance();
1627 sb.init(NULL);
1628 sb.closeEditSession(sb.getCharId());
1629 sb.waitOneMessage(CSessionBrowserImpl::getMessageName("on_invokeResult"));
1631 if (FarTP.requestFarTPToSession( (TSessionId)0, PlayerSelectedSlot, CFarTP::LaunchEditor, false ))
1633 WaitServerAnswer = true; // prepare to receive the character messages
1636 // // If the player clicked 'Launch Editor', there was no CONNECTION:SELECT_CHAR sent yet,
1637 // // so don't wait for the EGS to acknowledge our quit message as he does not know our character
1638 // LoginSM.pushEvent(CLoginStateMachine::ev_ingame_return);
1640 return;
1643 // Send CONNECTION:SELECT_CHAR
1644 CBitMemStream out;
1645 nlverify( GenericMsgHeaderMngr.pushNameToStream ("CONNECTION:SELECT_CHAR", out) );
1646 //nlinfo("impulseCallBack : CONNECTION:SELECT_CHAR '%d' sent.", PlayerSelectedSlot);
1649 CSelectCharMsg SelectCharMsg;
1650 SelectCharMsg.c = (uint8)PlayerSelectedSlot;
1651 out.serial (SelectCharMsg);
1652 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1654 NetMngr.push(out);
1655 NetMngr.send(NetMngr.getCurrentServerTick());
1658 //PlayerWantToGoInGame = true;
1660 // CBitMemStream out2;
1661 // if(GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ENTER", out2))
1662 // {
1663 // NetMngr.push(out2);
1664 // nlinfo("impulseCallBack : CONNECTION:ENTER sent");
1665 // }
1666 // else
1667 // nlwarning("unknown message name : 'CONNECTION:ENTER'.");
1669 WaitServerAnswer = true;
1670 if (ClientCfg.Local)
1671 serverReceivedReady = true;
1674 REGISTER_ACTION_HANDLER (CAHLaunchGame, "launch_game");
1677 // Ask the server to create a character
1678 // ------------------------------------------------------------------------------------------------
1679 class CAHAskCreateChar : public IActionHandler
1681 public:
1682 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1684 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1686 // Create the message for the server to create the character.
1687 CBitMemStream out;
1688 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out))
1690 nlwarning ("don't know message name CONNECTION:CREATE_CHAR");
1691 return;
1694 // Setup the name
1695 string sEditBoxPath = getParam (Params, "name");
1696 string sFirstName = "NotSet";
1697 string sSurName = "NotSet";
1698 CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(sEditBoxPath));
1699 if (pGEB != NULL)
1700 sFirstName = pGEB->getInputString();
1701 else
1702 nlwarning ("can't get edit box name : %s",sEditBoxPath.c_str());
1704 // Build the character summary from the database branch ui:temp:char3d
1705 CCharacterSummary CS;
1706 string sCharSumPath = getParam(Params, "charsum");
1707 SCharacter3DSetup::setupCharacterSummaryFromDB(CS, sCharSumPath);
1708 CS.Mainland = MainlandSelected;
1709 CS.Name = ucstring::makeFromUtf8(sFirstName); // FIXME: UTF-8 (serial)
1710 //CS.Surname = sSurName;
1712 // Create the message to send to the server from the character summary
1713 CCreateCharMsg CreateCharMsg;
1715 CreateCharMsg.setupFromCharacterSummary(CS);
1717 // Slot
1719 string sSlot = getParam(Params, "slot");
1721 CInterfaceExprValue result;
1722 if (!CInterfaceExpr::eval(sSlot, result))
1723 return;
1725 CreateCharMsg.Slot = (uint8)result.getInteger();
1727 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(PlayerSelectedSlot);
1730 // Setup the new career
1731 string sCaracBasePath = getParam (Params, "caracs");
1732 CreateCharMsg.NbPointFighter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FIGHT")->getValue32();
1733 CreateCharMsg.NbPointCaster = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"MAGIC")->getValue32();
1734 CreateCharMsg.NbPointCrafter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"CRAFT")->getValue32();
1735 CreateCharMsg.NbPointHarvester = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FORAGE")->getValue32();
1737 // Setup starting point
1738 string sLocationPath = getParam(Params, "loc");
1740 CreateCharMsg.StartPoint = RYZOM_STARTING_POINT::borea;
1742 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp (sLocationPath, false);
1743 if (pNL != NULL)
1744 CreateCharMsg.StartPoint = (RYZOM_STARTING_POINT::TStartPoint)(pNL->getValue64());
1745 else
1746 nlwarning(("Can't read starting point from the database : " + sLocationPath).c_str());
1748 if (CS.People == EGSPD::CPeople::Fyros)
1749 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::fyros_start));
1750 else if (CS.People == EGSPD::CPeople::Matis)
1751 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::matis_start));
1752 else if (CS.People == EGSPD::CPeople::Tryker)
1753 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::tryker_start));
1754 else // if (CS.People == EGSPD::CPeople::Zorai)
1755 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::zorai_start));
1759 // Send the message to the server
1760 CreateCharMsg.serialBitMemStream (out);
1761 if (!ClientCfg.Local/*!ClientCfg.Light*/)
1763 noUserChar = userChar = false;
1765 NetMngr.push(out);
1766 NetMngr.send(NetMngr.getCurrentServerTick());
1768 //nlinfo("impulseCallBack : CONNECTION:CREATE_CHAR sent");
1769 CreateCharMsg.dump();
1771 else
1773 userChar = true;
1774 if (CharacterSummaries.size() < 5)
1775 CharacterSummaries.push_back(CS);
1777 WaitServerAnswer = true;
1780 REGISTER_ACTION_HANDLER (CAHAskCreateChar, "ask_create_char");
1784 // Ask the server to delete a character
1785 // ------------------------------------------------------------------------------------------------
1786 class CAHAskDeleteChar : public IActionHandler
1788 public:
1789 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1791 // Create the message for the server to create the character.
1792 CBitMemStream out;
1793 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:DELETE_CHAR", out))
1795 nlwarning ("don't know message name CONNECTION:DELETE_CHAR");
1796 return;
1799 // Get the selected slot
1800 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1802 string sSlot = getParam(Params, "slot");
1804 CInterfaceExprValue result;
1805 if (!CInterfaceExpr::eval(sSlot, result))
1806 return;
1808 uint8 nSelectedSlot = (uint8)result.getInteger();
1809 if (nSelectedSlot >= CharacterSummaries.size())
1810 return;
1812 out.serial (nSelectedSlot);
1814 // Yoyo: delete the Local files. To avoid problem if recreate a character with same name.
1815 string playerName = CharacterSummaries[nSelectedSlot].Name.toUtf8();
1816 string playerDeletedFileName = buildPlayerNameForSaveFile(playerName);
1817 // Delete the 2 Local files
1818 pIM->deletePlayerConfig(playerDeletedFileName);
1819 pIM->deletePlayerKeys(playerDeletedFileName);
1821 // Send the message to the server
1822 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1824 noUserChar = userChar = false;
1825 NetMngr.push(out);
1826 NetMngr.send(NetMngr.getCurrentServerTick());
1828 //nlinfo("impulseCallBack : CONNECTION:DELETE_CHAR %d sent", nSelectedSlot);
1830 else
1832 if (nSelectedSlot < CharacterSummaries.size())
1833 CharacterSummaries.erase (CharacterSummaries.begin()+nSelectedSlot);
1834 if (CharacterSummaries.size() != 0)
1835 userChar = true;
1836 else
1837 noUserChar = true;
1839 WaitServerAnswer = true;
1842 REGISTER_ACTION_HANDLER (CAHAskDeleteChar, "ask_delete_char");
1844 // ------------------------------------------------------------------------------------------------
1845 string getTarget(CCtrlBase * /* ctrl */, const string &targetName)
1847 string sTmp = targetName;
1848 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1849 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1851 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1853 CInterfaceElement *elem = rTI.Elem;
1854 if (!elem)
1856 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1857 return "";
1859 const CReflectedProperty *pRP = CReflectSystem ::getProperty(elem->getReflectedClassName(), rTI.PropertyName);
1861 if (pRP->Type == CReflectedProperty::String)
1862 return ((elem->*(pRP->GetMethod.GetString))());
1863 return "";
1866 #ifdef RYZOM_LUA_UCSTRING
1867 // ------------------------------------------------------------------------------------------------
1868 ucstring getUCTarget(CCtrlBase * /* ctrl */, const string &targetName)
1870 string sTmp = targetName;
1871 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1872 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1874 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1876 CInterfaceElement *elem = rTI.Elem;
1877 if (!elem)
1879 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1880 return ucstring(""); // TODO: UTF-8 Lua
1882 const CReflectedProperty *pRP = elem->getReflectedProperty(rTI.PropertyName);
1884 if (pRP->Type == CReflectedProperty::UCString)
1885 return ((elem->*(pRP->GetMethod.GetUCString))());
1886 return ucstring(""); // TODO: UTF-8 Lua
1888 #endif
1890 /*// Ask the server to rename a character
1891 // ------------------------------------------------------------------------------------------------
1892 class CAHAskRenameChar : public IActionHandler
1894 public:
1895 virtual void execute (CCtrlBase *pCaller, const string &Params)
1897 string sName = getTarget(NULL,getParam(Params, "name"));
1898 string sSurname = getTarget(NULL,getParam(Params, "surname"));
1900 string sDBSlot = getParam(Params, "dbslot");
1902 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1903 uint8 nSelectedSlot = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sDBSlot,false)->getValue32();
1905 if (nSelectedSlot > CharacterSummaries.size())
1906 return;
1908 // Create the message for the server to create the character.
1909 CBitMemStream out;
1910 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:RENAME_CHAR", out))
1912 nlwarning ("don't know message name CONNECTION:RENAME_CHAR");
1913 return;
1916 // Get the selected slot
1917 out.serial (nSelectedSlot);
1918 out.serial (sName);
1919 out.serial (sSurname);
1921 // Send the message to the server
1922 if (!ClientCfg.Light)
1924 noUserChar = userChar = false;
1925 NetMngr.push (out);
1926 NetMngr.send (NetMngr.getCurrentServerTick());
1928 nldebug("impulseCallBack : CONNECTION:RENAME_CHAR sent");
1930 // Wait for the character message which describe all the characters on a server
1931 while (!noUserChar && !userChar)
1933 //NetMngr.waitForServer();
1934 NetMngr.update();
1935 NetMngr.send();
1936 nlSleep(100);
1939 else
1941 CharacterSummaries[nSelectedSlot].FirstName = sName;
1942 CharacterSummaries[nSelectedSlot].Surname = sSurname;
1946 REGISTER_ACTION_HANDLER (CAHAskRenameChar, "ask_rename_char");
1949 // Ask the server if the name is not already used
1950 // ------------------------------------------------------------------------------------------------
1951 class CAHAskValidName : public IActionHandler
1953 public:
1954 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1956 string sTarget = getParam(Params, "target");
1957 string sDBLink = getParam(Params, "dblink");
1958 CharNameValidDBLink = sDBLink;
1960 #ifdef RYZOM_LUA_UCSTRING
1961 string sName = getUCTarget(NULL,sTarget).toUtf8(); // TODO: UTF-8 Lua
1962 #else
1963 string sName = getTarget(NULL, sTarget);
1964 #endif
1966 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1967 if (sName.empty())
1969 NLGUI::CDBManager::getInstance()->getDbProp(sDBLink,false)->setValue32(0);
1970 return;
1973 // Ask the server
1974 CharNameValid = true;
1976 // PATCH DU BUG DE L'ESPACE !!!
1977 if (sName.find(' ') != ucstring::npos)
1978 CharNameValid = false;
1979 // PATCH DU BUG DE L'ESPACE !!!
1982 if (CharNameValid)
1984 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1987 CBitMemStream out;
1988 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ASK_NAME", out))
1990 nlwarning ("don't know message name CONNECTION:ASK_NAME");
1991 return;
1994 CCheckNameMsg checkNameMsg;
1995 checkNameMsg.Name = sName;
1996 checkNameMsg.HomeSessionId = MainlandSelected;
1997 checkNameMsg.serialBitMemStream(out);
1999 NewKeysCharNameWanted = sName;
2000 // append shard name
2001 for(uint k = 0; k < Mainlands.size(); ++k)
2003 if (Mainlands[k].Id == MainlandSelected)
2005 // extract name from mainland
2006 /*ucstring::size_type first = Mainlands[k].Name.find('('); // OLD
2007 ucstring::size_type last = Mainlands[k].Name.find(')');// OLD
2008 if (first != ucstring::npos && last != ucstring::npos && first < last)// OLD
2010 NewKeysCharNameWanted += Mainlands[k].Name.substr(first, last - first + 1);
2012 NewKeysCharNameWanted += ('(' + Mainlands[k].Name.toUtf8() + ')');
2013 break;
2017 NewKeysCharNameValidated.clear();
2019 NetMngr.push(out);
2020 NetMngr.send(NetMngr.getCurrentServerTick());
2022 //nlinfo("impulseCallBack : CONNECTION:ASK_NAME sent");
2024 // Wait for the valid character name message
2025 CharNameValidArrived = false;
2027 else
2030 CharNameValid = true;
2031 CharNameValidArrived = true;
2033 for (uint i = 0; i < CharacterSummaries.size(); ++i)
2035 string ls = CharacterSummaries[i].Name.toString();
2036 if (ls == sName)
2037 CharNameValid = false;
2041 else
2043 CharNameValidArrived = true;
2045 WaitServerAnswer = true;
2048 REGISTER_ACTION_HANDLER (CAHAskValidName, "ask_valid_name");
2050 // ------------------------------------------------------------------------------------------------
2051 class CAHPlaySound : public IActionHandler
2053 public:
2054 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2056 string sName = getParam(Params, "name");
2057 TStringId id = CStringMapper::map(sName);
2058 if (SoundMngr != NULL)
2059 SoundMngr->spawnSource(id,CVector(0,0,0));
2062 REGISTER_ACTION_HANDLER (CAHPlaySound, "play_sound");
2064 // ------------------------------------------------------------------------------------------------
2065 class CAHPlayMusicOutgame : public IActionHandler
2067 public:
2068 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2070 // get the name of the wanted music
2071 string sName = getParam(Params, "name");
2072 bool async;
2073 fromString(getParam(Params, "async"), async);
2075 // if empty name, return to default mode
2076 if (sName.empty())
2077 sName = ClientCfg.EmptySlotMusic;
2079 // change the music
2080 SoundGlobalMenu.setMusic(sName, async);
2083 REGISTER_ACTION_HANDLER (CAHPlayMusicOutgame, "play_music_outgame");
2085 // ------------------------------------------------------------------------------------------------
2086 class CAHRepeatUntil : public IActionHandler
2088 public:
2089 virtual void execute (CCtrlBase *pCaller, const string &Params)
2091 string sProc = getParam(Params, "proc");
2092 string sCond = getParam(Params, "cond");
2093 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2095 for(;;)
2097 vector<string> p;
2098 p.push_back(sProc);
2099 CWidgetManager::getInstance()->runProcedure(sProc, pCaller, p);
2101 CInterfaceExprValue result;
2102 if (CInterfaceExpr::eval(sCond, result))
2104 if (result.getBool())
2105 break;
2107 else
2109 break;
2115 REGISTER_ACTION_HANDLER (CAHRepeatUntil, "repeatuntil");
2118 // ------------------------------------------------------------------------------------------------
2119 class CAHDispInfo : public IActionHandler
2121 public:
2122 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2124 string sStr = getParam(Params, "str");
2125 string sVal = getParam(Params, "val");
2127 string res;
2129 CInterfaceExprValue result;
2130 if (CInterfaceExpr::eval(sStr, result))
2132 if (result.toString())
2134 res += result.getString();
2137 if (CInterfaceExpr::eval(sVal, result))
2139 if (result.toString())
2141 res += result.getString();
2145 nlinfo(res.c_str());
2148 REGISTER_ACTION_HANDLER (CAHDispInfo, "disp_info");
2151 // ***************************************************************************
2152 class CAHInitMainlandList : public IActionHandler
2154 public:
2156 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2158 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2160 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2161 if (pList == NULL)
2163 nlwarning("element " GROUP_LIST_MAINLAND " not found probably bad outgame.xml");
2164 return;
2167 CInterfaceGroup *pPrevLine = NULL;
2168 for(uint i = 0; i < Mainlands.size(); i++)
2170 vector< pair < string, string > > params;
2171 params.clear();
2172 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2173 if (i>0)
2174 params.push_back(pair<string,string>("posref", "BL TL"));
2176 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_mainland", GROUP_LIST_MAINLAND, params);
2177 if (pNewLine != NULL)
2179 CViewBase *pVBon = pNewLine->getView("online");
2180 CViewBase *pVBoff = pNewLine->getView("offline");
2181 if ((pVBon != NULL) && (pVBoff != NULL))
2183 pVBon->setActive(Mainlands[i].Online);
2184 pVBoff->setActive(!Mainlands[i].Online);
2187 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2188 if (pVT != NULL)
2190 std::string str = Mainlands[i].Name.toUtf8() + " " + Mainlands[i].Description.toUtf8();
2191 pVT->setTextLocalized(str, false);
2194 // Add to the list
2195 pNewLine->setParent(pList);
2196 pNewLine->setParentSize(pList);
2197 pNewLine->setParentPos(pPrevLine);
2198 pList->addGroup(pNewLine);
2200 pPrevLine = pNewLine;
2203 // UI Patch
2204 if (!Mainlands.empty())
2206 //choose default mainland from language code
2207 uint32 defaultMainland = 0;
2208 for(uint i = 0; i < Mainlands.size(); i++)
2210 if( Mainlands[i].LanguageCode == ClientCfg.LanguageCode )
2212 defaultMainland = i;
2213 break;
2217 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(Mainlands[defaultMainland].Id)+":but"));
2218 if (pCB != NULL)
2220 pCB->setPushed(true);
2221 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2224 pList->invalidateCoords();
2227 REGISTER_ACTION_HANDLER (CAHInitMainlandList, "init_mainland_list");
2230 // ***************************************************************************
2231 class CAHResetMainlandList : public IActionHandler
2233 public:
2235 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2237 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2238 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2239 pList->clearGroups();
2242 REGISTER_ACTION_HANDLER (CAHResetMainlandList, "reset_mainland_list");
2245 // ***************************************************************************
2246 class CAHMainlandSelect : public IActionHandler
2248 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2250 nlinfo("CAHMainlandSelect called");
2252 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2254 CCtrlButton *pCB = NULL;
2255 // Unselect
2256 if (MainlandSelected.asInt() != 0)
2258 pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(MainlandSelected)+":but"));
2259 if (pCB != NULL)
2260 pCB->setPushed(false);
2263 pCB = dynamic_cast<CCtrlButton*>(pCaller);
2264 if (pCB != NULL)
2266 string name = pCB->getId();
2267 name = name.substr(0,name.rfind(':'));
2268 uint32 mainland;
2269 fromString(name.substr(name.rfind(':')+1,name.size()), mainland);
2270 MainlandSelected = (TSessionId)mainland;
2272 pCB->setPushed(true);
2276 REGISTER_ACTION_HANDLER (CAHMainlandSelect, "mainland_select");
2279 // ***************************************************************************
2280 class CAHInitKeysetList : public IActionHandler
2282 public:
2286 CInterfaceGroup *PrevLine;
2287 CInterfaceGroup *List;
2288 bool First;
2290 CInterfaceGroup *buildTemplate(const std::string &templateName, const std::string &id)
2292 vector< pair < string, string > > params;
2293 params.clear();
2294 params.push_back(pair<string,string>("id", id));
2295 if (!First)
2297 params.push_back(pair<string,string>("posref", "BL TL"));
2299 First = false;
2300 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2301 return CWidgetManager::getInstance()->getParser()->createGroupInstance(templateName, GROUP_LIST_KEYSET, params);
2304 void addGroupInList(CInterfaceGroup *pNewLine)
2306 if (!pNewLine) return;
2307 // Add to the list
2308 pNewLine->setParent(List);
2309 pNewLine->setParentSize(List);
2310 pNewLine->setParentPos(PrevLine);
2311 List->addGroup(pNewLine);
2313 PrevLine = pNewLine;
2316 void addSeparator()
2318 addGroupInList(buildTemplate("t_keyseparator", ""));
2321 // add a new keyset in the list
2322 void addKeySet(const std::string &filename, const std::string &name, const std::string tooltip)
2324 nlassert(List);
2325 CInterfaceGroup *pNewLine = buildTemplate("t_keyset", toString(filename));
2326 if (pNewLine != NULL)
2328 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2329 if (pVT != NULL)
2331 pVT->setTextLocalized(name, false);
2334 CCtrlBase *pBut = pNewLine->getCtrl("but");
2335 if (pBut != NULL)
2337 pBut->setDefaultContextHelp(tooltip);
2339 addGroupInList(pNewLine);
2343 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2345 NewKeysCharNameWanted.clear();
2346 NewKeysCharNameValidated.clear();
2347 GameKeySet = "keys.xml";
2348 RingEditorKeySet = "keys_r2ed.xml";
2349 First = true;
2350 PrevLine = NULL;
2351 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2353 List = dynamic_cast<CInterfaceGroup *>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2354 if (List == NULL)
2356 nlwarning("element " GROUP_LIST_KEYSET " not found probably bad outgame.xml");
2357 return;
2360 // built-in keysets
2361 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2362 sint wasdIndex = -1;
2363 sint zqsdIndex = -1;
2364 if (keySetVar && keySetVar->size() != 0)
2366 for (uint k = 0; k < keySetVar->size(); ++k)
2368 if (keySetVar->asString(k) == "zqsd") zqsdIndex = (sint) k;
2369 if (keySetVar->asString(k) == "wasd") wasdIndex = (sint) k;
2371 std::string strId = "uiCP_KeysetName_" + keySetVar->asString(k);
2372 strFindReplace(strId, ".", "_");
2373 const string &keySetName = CI18N::get(strId);
2374 strId = "uiCP_KeysetTooltip_" + keySetVar->asString(k);
2375 strFindReplace(strId, ".", "_");
2376 if (CI18N::hasTranslation(strId))
2378 const string &keySetTooltip = CI18N::get(strId);
2379 addKeySet(keySetVar->asString(k), keySetName, keySetTooltip);
2383 else
2385 nlwarning("'%s' var not found in config file, or list is empty, proposing default keyset only", KeySetVarName);
2386 std::string defaultKeySet = "keys";
2387 const string &keySetName = CI18N::get("uiCP_KeysetName_" + defaultKeySet);
2388 const string &keySetTooltip = CI18N::get("uiCP_KeysetTooltip_" + defaultKeySet);
2389 addKeySet(defaultKeySet, keySetName, keySetTooltip);
2392 // keyset from previous chars
2393 std::vector<std::string> savedFiles;
2394 CPath::getPathContent("save/", false, false, true, savedFiles);
2395 enum { GameKeys = 0x1, EditorKeys = 0x2 };
2396 typedef std::map<std::string, uint> TKeySetFileMap;
2397 TKeySetFileMap keySetFiles; // combination of 'GameKeys' & 'EditorKeys' flag for each character
2398 for (uint k = 0; k < savedFiles.size(); ++k)
2400 if (testWildCard(CFile::getFilename(savedFiles[k]), "keys_*.xml"))
2402 bool editorKeys = testWildCard(CFile::getFilename(savedFiles[k]), "keys_r2ed_*.xml");
2403 std::string baseName = CFile::getFilenameWithoutExtension(savedFiles[k]).substr(strlen(editorKeys ? "keys_r2ed_" : "keys_"));
2404 if(!keySetFiles.count(baseName)) keySetFiles[baseName] = 0;
2405 keySetFiles[baseName] |= editorKeys ? EditorKeys : GameKeys;
2409 bool separatorAdded = false;
2410 if (!keySetFiles.empty())
2412 for(TKeySetFileMap::iterator it = keySetFiles.begin(); it != keySetFiles.end(); ++it)
2414 string name;
2415 if (ClientCfg.Local)
2417 name = it->first;
2419 else
2421 // search matching utf-8 string name from character summaries
2422 for (uint k = 0; k < CharacterSummaries.size(); ++k)
2424 if (it->first == buildPlayerNameForSaveFile(CharacterSummaries[k].Name.toUtf8()))
2426 name = CharacterSummaries[k].Name.toUtf8();
2430 if (!name.empty())
2432 if (!separatorAdded)
2434 addSeparator();
2435 separatorAdded = true;
2437 addKeySet(it->first, it->first, CI18N::get(std::string("uiCP_KeysetImport") + (it->second & GameKeys ? "_Game" : "")
2438 + (it->second & EditorKeys ? "_Editor" : "")));
2443 // default to 'ZQSD' for French and Belgian keyboard, 'WASD' else
2444 bool wasd = !CSystemUtils::isAzertyKeyboard();
2446 /*sint startIndex = wasd ? wasdIndex : zqsdIndex;
2447 if (startIndex == -1) startIndex = 0;
2449 // TMP TMP : no way to have 2 keys for the same action for now -> default to 'arrows' setting.
2450 sint startIndex = 0;
2451 nlassert(startIndex >= 0);
2452 if (startIndex < (sint) List->getNumGroup())
2454 CInterfaceGroup *gr = dynamic_cast<CInterfaceGroup *>(List->getGroup(startIndex));
2455 if (gr)
2457 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(gr->getCtrl("but"));
2458 if (pCB != NULL)
2460 pCB->setPushed(true);
2461 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2465 List->invalidateCoords();
2468 REGISTER_ACTION_HANDLER (CAHInitKeysetList, "init_keyset_list");
2471 // ***************************************************************************
2472 class CAHResetKeysetList : public IActionHandler
2474 public:
2476 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2478 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2479 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2480 pList->clearGroups();
2483 REGISTER_ACTION_HANDLER (CAHResetKeysetList, "reset_keyset_list");
2486 // ***************************************************************************
2487 class CAHResetKeysetSelect : public IActionHandler
2489 public:
2490 std::string getIdPostFix(const std::string fullId)
2492 std::string::size_type pos = fullId.find_last_of(":");
2493 if (pos != std::string::npos)
2495 return fullId.substr(pos + 1);
2497 return "";
2499 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2501 if (!pCaller) return;
2502 // 'unpush' all groups but the caller
2504 struct CUnpush : public CInterfaceElementVisitor
2506 CCtrlBase *Ref;
2507 virtual void visitCtrl(CCtrlBase *ctrl)
2509 if (ctrl == Ref) return;
2510 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton *>(ctrl);
2511 if (but)
2513 but->setPushed(false);
2517 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2518 CInterfaceGroup * list = dynamic_cast<CInterfaceGroup *>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2519 if (list)
2521 CUnpush unpusher;
2522 unpusher.Ref = pCaller;
2523 list->visit(&unpusher);
2525 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton *>(pCaller);
2526 if (but)
2528 but->setPushed(true);
2531 GameKeySet = "keys.xml";
2532 RingEditorKeySet = "keys_r2ed.xml";
2533 if (!pCaller->getParent()) return;
2534 // compute the 2 filenames from the id
2535 // if id is in the built-in keysets :
2536 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2537 if (keySetVar && keySetVar->size() != 0)
2539 for (uint k = 0; k < keySetVar->size(); ++k)
2541 std::string id = getIdPostFix(pCaller->getParent()->getId());
2542 if (keySetVar->asString(k) == id)
2544 GameKeySet = "keys" + string(id.empty() ? "" : "_") + id + ".xml";
2545 RingEditorKeySet = "keys_r2ed" + string(id.empty() ? "" : "_") + id + ".xml";
2546 return;
2550 // ... else maybe from a previous character ?
2551 if (CFile::isExists("save/keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") )
2553 GameKeySet = "keys_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml";
2555 if (CFile::isExists("save/keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml") )
2557 RingEditorKeySet = "keys_r2ed_" + getIdPostFix(pCaller->getParent()->getId()) + ".xml";
2559 // NB : key file will be copied for real when the new 'character summary' is
2563 REGISTER_ACTION_HANDLER (CAHResetKeysetSelect, "keyset_select");
2569 // *************************** SCENARIO CONTROL WINDOW ***********************
2570 // ***************************************************************************
2571 // helper function for "setScenarioInformation"
2572 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const std::string &text)
2574 CInterfaceElement *result = scenarioWnd->findFromShortId(uiName);
2575 if(result)
2577 CViewText* viewText = dynamic_cast<CViewText*>(result);
2578 if(viewText)
2579 viewText->setTextLocalized(text, false);
2580 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2581 if(editBox)
2582 editBox->setInputString(text);
2586 // helper function for "setScenarioInformation"
2587 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const ucstring &text) // TODO: UTF-8 Lua
2589 setTextField(scenarioWnd, uiName, text.toUtf8());
2591 // helper function for "setScenarioInformation"
2592 static std::string fieldLookup(const vector< pair< string, string > > &values, const std::string &id)
2594 for(uint i=0; i<values.size(); i++)
2596 if (values[i].first == id) return values[i].second;
2598 return "--";
2601 static void setScenarioInformation(CInterfaceGroup* scenarioWnd, const string scenarioName)
2603 vector< pair< string, string > > values;
2604 if(R2::getEditor().isInitialized())
2606 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
2608 else
2610 R2::CScenarioValidator sv;
2611 std::string md5, signature;
2612 sv.setScenarioToLoad(scenarioName, values, md5, signature, false);
2615 setTextField(scenarioWnd, "rules_value_text", fieldLookup(values, "Rules"));
2616 uint levelRange = 0;
2617 uint32 nLevel;
2618 fromString(fieldLookup(values, "Level"), nLevel);
2619 switch(nLevel)
2621 case 20: levelRange = 0; break;
2622 case 50: levelRange = 1; break;
2623 case 100: levelRange = 2; break;
2624 case 150: levelRange = 3; break;
2625 case 200: levelRange = 4; break;
2626 case 250: levelRange = 5; break;
2628 setTextField(scenarioWnd, "level_value_text", CI18N::get("uiRAP_Level" + toString(levelRange)));
2629 setTextField(scenarioWnd, "language_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Language")));
2630 setTextField(scenarioWnd, "type_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Type")));
2631 setTextField(scenarioWnd, "edit_small_description", fieldLookup(values, "ShortDescription"));
2632 if(R2::getEditor().isInitialized())
2634 setTextField(scenarioWnd, "scenario_value_text", "'" + fieldLookup(values, "Title") + "'");
2639 void getChildrenControls(CInterfaceGroup* group, std::vector<CCtrlBase*> & controls)
2641 for(uint i=0; i<group->getGroups().size(); i++)
2642 getChildrenControls(group->getGroups()[i], controls);
2644 for(uint i=0; i<group->getControls().size(); i++)
2645 controls.push_back(group->getControls()[i]);
2648 inline void setToggleButton(CInterfaceGroup* scenarioWnd, const string & buttonName, bool pushed)
2650 CInterfaceElement * result = scenarioWnd->findFromShortId(buttonName);
2651 if(result)
2653 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
2654 if(group)
2656 result = group->findFromShortId(string("toggle_butt"));
2657 if(result)
2659 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2660 if(baseButton)
2661 baseButton->setPushed(!pushed);
2668 class CAHScenarioControl : public IActionHandler
2670 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2672 nlinfo("CAHScenarioControl called");
2674 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2675 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2676 if(!scenarioWnd) return;
2678 // -------- active some groups in function of Ryzom mode or Edition/Animation mode ----
2679 // active team toggle button?
2680 CInterfaceElement *result = scenarioWnd->findFromShortId(string("invite_team"));
2681 if(result)
2683 CInterfaceGroup* groupTeam = dynamic_cast<CInterfaceGroup*>(result);
2684 if(groupTeam)
2686 bool team = !(R2::getEditor().isInitialized());
2687 if(team)
2688 team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2689 groupTeam->setActive(team);
2693 // set scenario name label
2694 result = scenarioWnd->findFromShortId(string("current_scenario_label_text"));
2695 if(result)
2697 CViewText* viewText = dynamic_cast<CViewText*>(result);
2698 if(viewText)
2700 viewText->setTextLocalized(R2::getEditor().isInitialized() ? "uiR2EDScenarioName" : "uiR2EDScenarioFileName", true);
2704 // ok button tranlation
2705 result = scenarioWnd->findFromShortId(string("ok_button"));
2706 if(result)
2708 CCtrlTextButton* okButton = dynamic_cast<CCtrlTextButton*>(result);
2709 if(okButton)
2711 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
2712 okButton->setHardText(CI18N::get("uiR2EDLaunchScenario"));
2713 else
2714 okButton->setHardText(CI18N::get("uiR2EDApplyScenarioFilters"));
2718 // init current scenario name and parameters
2719 if(!R2::getEditor().isInitialized())
2721 ScenarioFileName.clear();
2723 // empty scenario
2724 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2725 if(result)
2727 CViewText* viewText= dynamic_cast<CViewText*>(result);
2729 if(viewText)
2730 viewText->setText(std::string());
2733 setScenarioInformation(scenarioWnd, "");
2735 // hide description and information?
2736 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2737 if(result)
2738 result->setActive(R2::getEditor().isInitialized());
2740 result = scenarioWnd->findFromShortId(string("description_gr"));
2741 if(result)
2742 result->setActive(R2::getEditor().isInitialized());
2744 // mainlands list
2745 result = scenarioWnd->findFromShortId(string("shards"));
2746 if(result)
2748 CGroupList * shardList = dynamic_cast<CGroupList*>(result);
2749 if(shardList)
2751 shardList->deleteAllChildren();
2753 for(uint i = 0; i < Mainlands.size(); i++)
2755 vector< pair < string, string > > params;
2756 params.clear();
2757 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2758 params.push_back(pair<string,string>("w", "1024"));
2759 params.push_back(pair<string,string>("tooltip", "uiRingFilterShard"));
2760 CInterfaceGroup *toggleGr = CWidgetManager::getInstance()->getParser()->createGroupInstance("label_toggle_button", shardList->getId(), params);
2761 shardList->addChild(toggleGr);
2762 // set unicode name
2763 CViewText *shardName = dynamic_cast<CViewText *>(toggleGr->getView("button_text"));
2764 if (shardName)
2766 shardName->setTextLocalized(Mainlands[i].Name.toUtf8(), false);
2772 // show/display "back" button
2773 result = scenarioWnd->findFromShortId(string("load_button"));
2774 if(result)
2776 CCtrlBaseButton * loadB = dynamic_cast<CCtrlBaseButton *>(result);
2777 if(loadB)
2779 loadB->setActive(!R2::getEditor().isInitialized());
2783 // fill toggle buttons
2784 if(R2::getEditor().getAccessMode()==R2::CEditor::AccessDM)
2786 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
2787 sessionBrowser.getSessionInfo(sessionBrowser.getCharId(), R2::getEditor().getDMC().getEditionModule().getCurrentAdventureId());
2789 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_sessionInfoResult")))
2791 TRaceFilter & raceFilter = sessionBrowser._LastRaceFilter;
2792 setToggleButton(scenarioWnd, "fyros", raceFilter.checkEnumValue(TRaceFilterEnum::rf_fyros));
2793 setToggleButton(scenarioWnd, "matis", raceFilter.checkEnumValue(TRaceFilterEnum::rf_matis));
2794 setToggleButton(scenarioWnd, "tryker", raceFilter.checkEnumValue(TRaceFilterEnum::rf_tryker));
2795 setToggleButton(scenarioWnd, "zorai", raceFilter.checkEnumValue(TRaceFilterEnum::rf_zorai));
2797 TReligionFilter & religionFilter = sessionBrowser._LastReligionFilter;
2798 setToggleButton(scenarioWnd, "kami", religionFilter.checkEnumValue(TReligionFilterEnum::rf_kami));
2799 setToggleButton(scenarioWnd, "karavan", religionFilter.checkEnumValue(TReligionFilterEnum::rf_karavan));
2800 setToggleButton(scenarioWnd, "neutral", religionFilter.checkEnumValue(TReligionFilterEnum::rf_neutral));
2802 TGuildFilter & guildFilter = sessionBrowser._LastGuildFilter;
2803 setToggleButton(scenarioWnd, "guild_gr", (guildFilter==TGuildFilter::gf_any_player));
2805 TShardFilter & shardFilter = sessionBrowser._LastShardFilter;
2806 for(uint i=0; i<Mainlands.size(); i++)
2807 setToggleButton(scenarioWnd, toString(Mainlands[i].Id), shardFilter.checkEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i)));
2809 TLevelFilter & levelFilter = sessionBrowser._LastLevelFilter;
2810 setToggleButton(scenarioWnd, "20", levelFilter.checkEnumValue(TLevelFilterEnum::lf_a));
2811 setToggleButton(scenarioWnd, "50", levelFilter.checkEnumValue(TLevelFilterEnum::lf_b));
2812 setToggleButton(scenarioWnd, "100", levelFilter.checkEnumValue(TLevelFilterEnum::lf_c));
2813 setToggleButton(scenarioWnd, "150", levelFilter.checkEnumValue(TLevelFilterEnum::lf_d));
2814 setToggleButton(scenarioWnd, "200", levelFilter.checkEnumValue(TLevelFilterEnum::lf_e));
2815 setToggleButton(scenarioWnd, "250", levelFilter.checkEnumValue(TLevelFilterEnum::lf_f));
2817 bool subscriptionClosed = sessionBrowser._LastSubscriptionClosed;
2818 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2819 if(result)
2821 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2822 if(baseButton)
2823 baseButton->setPushed(subscriptionClosed);
2826 bool autoInvite = sessionBrowser._LastAutoInvite;
2827 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2828 if(result)
2830 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2831 if(baseButton)
2832 baseButton->setPushed(!autoInvite);
2835 // description
2836 string description = sessionBrowser._LastDescription;
2837 if(!description.empty())
2839 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2840 if(result)
2842 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2843 if(editBox)
2844 editBox->setInputString(description);
2848 else
2850 nlwarning("getSessionInfo callback return false");
2853 else
2855 result = scenarioWnd->findFromShortId(string("access_players_filter"));
2856 if(result)
2858 CInterfaceGroup* filtersGroup = dynamic_cast<CInterfaceGroup*>(result);
2859 if(filtersGroup)
2861 std::vector<CCtrlBase*> controls;
2862 getChildrenControls(filtersGroup, controls);
2863 for(uint i=0; i<controls.size(); i++)
2865 CCtrlBase* control = controls[i];
2866 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(control);
2867 if(baseButton && (baseButton->getType()==CCtrlBaseButton::ToggleButton))
2868 baseButton->setPushed(false);
2875 REGISTER_ACTION_HANDLER (CAHScenarioControl, "init_scenario_control");
2878 // ***************************************************************************
2879 class CAHScenarioInformation : public IActionHandler
2881 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2883 nlinfo("CAHScenarioDescription called");
2885 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2886 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2887 if(!scenarioWnd) return;
2889 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2890 if(result)
2892 CViewText* viewText= dynamic_cast<CViewText*>(result);
2894 if(viewText)
2896 ScenarioFileName = getParam(Params, "ScenarioName");
2897 setScenarioInformation(scenarioWnd, ScenarioFileName);
2899 string scenarioName = ScenarioFileName;
2900 string::size_type posScenarioName = 0;
2901 while(posScenarioName!=string::npos)
2903 scenarioName = scenarioName.substr(posScenarioName==0?posScenarioName:posScenarioName+1);
2904 posScenarioName = scenarioName.find('/');
2906 viewText->setTextLocalized(scenarioName, false);
2910 // active description and information
2911 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2912 if(result)
2913 result->setActive(true);
2915 result = scenarioWnd->findFromShortId(string("description_gr"));
2916 if(result)
2917 result->setActive(true);
2920 REGISTER_ACTION_HANDLER (CAHScenarioInformation, "scenario_information");
2922 // ***************************************************************************
2923 class CAHHideCharsFilters : public IActionHandler
2925 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2927 nlinfo("CAHHideCharsFilters called");
2929 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2930 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2931 if(!scenarioWnd) return;
2933 bool lookingForPlayers = true;
2934 CInterfaceElement *result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2935 if(result)
2937 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2938 if(baseButton)
2939 lookingForPlayers = !baseButton->getPushed(); // warning : on / off textures are inverted !!!
2942 result = scenarioWnd->findFromShortId(string("access_body_gr"));
2943 if(result)
2944 result->setActive(lookingForPlayers);
2946 result = scenarioWnd->findFromShortId(string("sep_global_access"));
2947 if(result)
2948 result->setActive(lookingForPlayers);
2950 result = scenarioWnd->findFromShortId(string("auto_invite_label"));
2951 if(result)
2952 result->setActive(lookingForPlayers);
2954 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2955 if(result)
2956 result->setActive(lookingForPlayers);
2958 result = scenarioWnd->findFromShortId(string("invite_team"));
2959 if(result)
2961 bool team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2962 team = (team && !(R2::getEditor().isInitialized()) && lookingForPlayers);
2963 result->setActive(team);
2967 REGISTER_ACTION_HANDLER (CAHHideCharsFilters, "hide_chars_filters");
2969 // ***************************************************************************
2970 class CAHLoadScenario : public IActionHandler
2972 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2974 nlinfo("CAHLoadScenario called");
2976 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2977 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2978 if(!scenarioWnd) return;
2980 CInterfaceElement *result = NULL;
2982 // load scenario
2983 if(!R2::getEditor().isInitialized())
2985 R2::CEditor::setStartingAnimationFilename(ScenarioFileName);
2988 // description
2989 string description;
2990 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2991 if(result)
2993 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2994 if(editBox)
2995 description = editBox->getInputString();
2998 // races
2999 map<string, bool> races;
3000 races["fyros"] = false;
3001 races["matis"] = false;
3002 races["tryker"] = false;
3003 races["zorai"] = false;
3004 for(map<string, bool>::iterator itRace=races.begin(); itRace!=races.end(); itRace++)
3006 result = scenarioWnd->findFromShortId(itRace->first);
3007 if(result)
3009 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3010 if(group)
3012 result = group->findFromShortId(string("toggle_butt"));
3013 if(result)
3015 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3016 if(baseButton)
3017 itRace->second = !baseButton->getPushed();
3023 // religion
3024 map<string, bool> religions;
3025 religions["kami"] = false;
3026 religions["karavan"] = false;
3027 religions["neutral"] = false;
3028 for(map<string, bool>::iterator itReligion=religions.begin(); itReligion!=religions.end(); itReligion++)
3030 result = scenarioWnd->findFromShortId(itReligion->first);
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 itReligion->second = !baseButton->getPushed();
3047 // guild
3048 bool anyPlayer = false;
3049 result = scenarioWnd->findFromShortId(string("guild_gr"));
3050 if(result)
3052 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3053 if(group)
3055 result = group->findFromShortId(string("toggle_butt"));
3056 if(result)
3058 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3059 if(baseButton)
3060 anyPlayer = !baseButton->getPushed();
3065 // shards
3066 std::vector<bool> shards(Mainlands.size(), false);
3067 for(uint i=0; i<Mainlands.size(); i++)
3069 string firstKey = Mainlands[i].Description.toString();
3071 result = scenarioWnd->findFromShortId(toString(Mainlands[i].Id));
3072 if(result)
3074 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3075 if(group)
3077 result = group->findFromShortId(string("toggle_butt"));
3078 if(result)
3080 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3081 if(baseButton)
3082 shards[i] = !baseButton->getPushed();
3088 // levels
3089 map<string, bool> levels;
3090 levels["20"] = false;
3091 levels["50"] = false;
3092 levels["100"] = false;
3093 levels["150"] = false;
3094 levels["200"] = false;
3095 levels["250"] = false;
3096 for(map<string, bool>::iterator itLevel=levels.begin(); itLevel!=levels.end(); itLevel++)
3098 result = scenarioWnd->findFromShortId(itLevel->first);
3099 if(result)
3101 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3102 if(group)
3104 result = group->findFromShortId(string("toggle_butt"));
3105 if(result)
3107 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3108 if(baseButton)
3109 itLevel->second = !baseButton->getPushed();
3115 // global access
3116 bool globalAccess = false;
3117 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
3118 if(result)
3120 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3121 if(baseButton)
3122 globalAccess = !baseButton->getPushed();
3125 // auto invite
3126 bool autoInvite = false;
3127 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
3128 if(result)
3130 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3131 if(baseButton)
3132 autoInvite = !baseButton->getPushed();
3135 // invite your team
3136 bool inviteTeam = false;
3137 result = scenarioWnd->findFromShortId(string("team_toggle_butt"));
3138 if(result)
3140 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3141 if(baseButton)
3142 inviteTeam = !baseButton->getPushed();
3145 bool launchScenarioFromRingAccessPoint = false;
3147 vector< pair< string, string > > values;
3148 if(R2::getEditor().isInitialized())
3150 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
3152 else
3154 R2::CScenarioValidator sv;
3155 std::string md5, signature;
3156 sv.setScenarioToLoad(ScenarioFileName, values, md5, signature, false);
3157 launchScenarioFromRingAccessPoint = true;
3160 string rules, level, title;
3161 string initialIsland, initialEntryPoint, initialSeason;
3162 std::string lang, scenarioType;
3163 std::string otherCharAccess;
3164 std::string nevraxScenario = "0";
3165 std::string trialAllowed = "0";
3166 for(uint i=0; i<values.size(); i++)
3168 std::pair<std::string, std::string> pair = values[i];
3170 if(pair.first == "Rules") rules = pair.second;
3171 else if(pair.first == "Level") level = pair.second;
3172 else if(pair.first == "Title") title = pair.second;
3173 else if(pair.first == "InitialIsland") initialIsland = pair.second;
3174 else if(pair.first == "InitialEntryPoint") initialEntryPoint = pair.second;
3175 else if(pair.first == "InitialSeason") initialSeason = pair.second;
3176 else if(pair.first == "Language") lang = pair.second;
3177 else if(pair.first == "Type") scenarioType = pair.second;
3178 else if(pair.first == "OtherCharAccess") otherCharAccess = pair.second;
3179 else if(pair.first == "NevraxScenario") nevraxScenario = pair.second;
3180 else if(pair.first == "TrialAllowed") trialAllowed = pair.second;
3183 uint nLevel;
3184 fromString(level, nLevel);
3185 R2::TSessionLevel sessionLevel = R2::TSessionLevel::TValues(nLevel/50 + 1);
3187 // ---- fix for old scenarii
3188 if (lang == "French")
3189 lang = "fr";
3190 else if (lang == "German" || lang == "Deutsch")
3191 lang = "de";
3192 else //if (lang == "English")
3193 lang = "en";
3195 if (nlstricmp(scenarioType, "Roleplay") == 0 || nlstricmp(scenarioType, "Role play") == 0)
3196 scenarioType = "so_story_telling";
3197 else if (nlstricmp(scenarioType, "Combat") == 0)
3198 scenarioType = "so_hack_slash";
3199 // --------------------------
3201 TRuleType ruleType(TRuleType::rt_strict);
3202 if(rules==CI18N::get("uiR2EDliberal"))
3203 ruleType = TRuleType(TRuleType::rt_liberal);
3204 else if(rules == CI18N::get("uiR2EDstrict"))
3205 ruleType = TRuleType(TRuleType::rt_strict);
3206 volatile static bool override = false;
3207 if (override)
3209 if(rules== "Masterless")
3210 ruleType = TRuleType(TRuleType::rt_liberal);
3211 else if(rules == "Mastered")
3212 ruleType = TRuleType(TRuleType::rt_strict);
3215 TRaceFilter raceFilter;
3216 if(races["fyros"])
3217 raceFilter.setEnumValue(TRaceFilterEnum::rf_fyros);
3218 if(races["matis"])
3219 raceFilter.setEnumValue(TRaceFilterEnum::rf_matis);
3220 if(races["tryker"])
3221 raceFilter.setEnumValue(TRaceFilterEnum::rf_tryker);
3222 if(races["zorai"])
3223 raceFilter.setEnumValue(TRaceFilterEnum::rf_zorai);
3225 TReligionFilter religionFilter;
3226 if(religions["kami"])
3227 religionFilter.setEnumValue(TReligionFilterEnum::rf_kami);
3228 if(religions["karavan"])
3229 religionFilter.setEnumValue(TReligionFilterEnum::rf_karavan);
3230 if(religions["neutral"])
3231 religionFilter.setEnumValue(TReligionFilterEnum::rf_neutral);
3233 TGuildFilter guildFilter(anyPlayer?TGuildFilter::gf_any_player:TGuildFilter::gf_only_my_guild);
3235 TShardFilter shardFilter;
3236 for (uint i = 0; i < shards.size(); ++i)
3238 if (shards[i]) shardFilter.setEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i));
3241 TLevelFilter levelFilter;
3242 if(levels["20"])
3243 levelFilter.setEnumValue(TLevelFilterEnum::lf_a);
3244 if(levels["50"])
3245 levelFilter.setEnumValue(TLevelFilterEnum::lf_b);
3246 if(levels["100"])
3247 levelFilter.setEnumValue(TLevelFilterEnum::lf_c);
3248 if(levels["150"])
3249 levelFilter.setEnumValue(TLevelFilterEnum::lf_d);
3250 if(levels["200"])
3251 levelFilter.setEnumValue(TLevelFilterEnum::lf_e);
3252 if(levels["250"])
3253 levelFilter.setEnumValue(TLevelFilterEnum::lf_f);
3255 uint32 charId = 0;
3256 if (!ClientCfg.Local)
3257 charId = (NetMngr.getLoginCookie().getUserId()<< 4) + (uint32) PlayerSelectedSlot;
3259 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
3261 if(R2::getEditor().getAccessMode() != R2::CEditor::AccessDM)
3263 bool noob = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IS_NEWBIE")->getValueBool();
3264 if (FreeTrial && noob && (nevraxScenario != "1" || trialAllowed != "1"))
3266 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3267 if (pVT != NULL)
3268 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3269 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3271 return;
3276 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
3278 if (launchScenarioFromRingAccessPoint)
3280 // hibernate Edit Session if active
3281 sessionBrowser.hibernateEditSession(charId);
3282 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3284 nlwarning("hibernateEditSession callback return false");
3289 // schedule session
3290 bool launchSuccess = true;
3291 sessionBrowser.scheduleSession(charId, TSessionType::st_anim,
3292 title, description, sessionLevel,
3293 /*TAccessType::at_public,*/ ruleType, TEstimatedDuration::et_medium, 0, TAnimMode::am_dm,
3294 raceFilter, religionFilter, guildFilter, shardFilter, levelFilter, lang, RSMGR::TSessionOrientation(scenarioType),
3295 !globalAccess, autoInvite);
3297 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_scheduleSessionResult")))
3299 if(sessionBrowser._LastScheduleSessionResult==0)
3301 // start session
3302 sessionBrowser.startSession(sessionBrowser._LastScheduleSessionCharId,
3303 sessionBrowser._LastScheduleSessionId);
3305 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3308 if (launchScenarioFromRingAccessPoint)
3310 if (!initialIsland.empty() && !initialEntryPoint.empty() && !initialSeason.empty())
3312 sessionBrowser.setSessionStartParams(charId, sessionBrowser._LastScheduleSessionId, initialIsland, initialEntryPoint, initialSeason);
3316 TSessionPartStatus sessionStatus;
3317 if(ruleType==TRuleType::rt_liberal)
3318 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_play_invited);
3319 else
3320 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_anim_invited);
3322 // invite player
3323 sessionBrowser.inviteCharacter(
3324 sessionBrowser._LastScheduleSessionCharId,
3325 sessionBrowser._LastScheduleSessionId,
3326 sessionBrowser._LastScheduleSessionCharId,
3327 sessionStatus.toString());
3329 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3331 // request session
3332 FarTP.requestFarTPToSession(sessionBrowser._LastScheduleSessionId, PlayerSelectedSlot, CFarTP::JoinSession,
3333 !R2::getEditor().isInitialized());
3335 else
3337 nlwarning("inviteCharacter callback return false");
3340 if (sessionBrowser._LastInvokeResult != 0)
3342 nlwarning("inviteCharacter callback use error values %d", sessionBrowser._LastInvokeResult);
3345 if(sessionBrowser._LastInvokeResult == 14)
3347 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3348 if (pVT != NULL)
3349 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3350 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3354 // invite team
3355 if(inviteTeam)
3357 for (uint i = 0 ; i < 8 ; ++i)
3359 uint32 val = NLGUI::CDBManager::getInstance()->getDbProp(NLMISC::toString("SERVER:GROUP:%d:NAME",i))->getValue32();
3360 if(val!=0)
3362 STRING_MANAGER::CStringManagerClient *pSMC = STRING_MANAGER::CStringManagerClient::instance();
3363 string res;
3364 if (pSMC->getString(val,res))
3366 string charName = CEntityCL::removeTitleAndShardFromName(res);
3367 sessionBrowser.inviteCharacterByName(sessionBrowser._LastScheduleSessionCharId, charName);
3369 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3371 nlwarning("inviteCharacterByName callback return false");
3374 if(sessionBrowser._LastInvokeResult == 14)
3376 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3377 if (pVT != NULL)
3378 pVT->setTextLocalized("uiRingWarningInviteFreeTrial", true);
3379 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3386 else
3388 nlwarning("startSession callback return false");
3389 launchSuccess = false;
3392 else if(sessionBrowser._LastScheduleSessionResult==10)
3394 pIM->messageBoxWithHelp(CI18N::get("uiRingWarningBanishedPlayer"));
3396 else
3398 launchSuccess=false;
3401 else
3403 nlwarning("scheduleSession callback return false");
3404 launchSuccess = false;
3407 if(!launchSuccess)
3409 pIM->messageBoxWithHelp(CI18N::get("uiRingLaunchScenarioError"));
3411 else
3413 scenarioWnd->setActive(false);
3416 else
3418 // update session
3419 sessionBrowser.updateSessionInfo(charId, sessionBrowser._LastScheduleSessionId, title, 0, description, sessionLevel,
3420 /*TAccessType::at_public, */TEstimatedDuration::et_medium, 0, raceFilter, religionFilter,
3421 guildFilter, shardFilter, levelFilter, !globalAccess, autoInvite, lang, RSMGR::TSessionOrientation(scenarioType));
3423 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3425 nlwarning("updateSessionInfo callback return false");
3426 pIM->messageBoxWithHelp(CI18N::get("uiRingUpdateScenarioFiltersError"));
3428 else
3430 scenarioWnd->setActive(false);
3435 REGISTER_ACTION_HANDLER (CAHLoadScenario, "load_scenario");
3438 // ***************************************************************************
3439 class CAHOpenRingSessions : public IActionHandler
3441 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3443 if(!R2::getEditor().isInitialized())
3445 CInterfaceManager *pIM = CInterfaceManager::getInstance();
3446 CInterfaceGroup* ringSessionsWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:ring_sessions"));
3447 if(!ringSessionsWnd) return;
3448 ringSessionsWnd->setActive(true);
3452 REGISTER_ACTION_HANDLER (CAHOpenRingSessions, "open_ring_sessions");
3454 // ***************************************************************************
3455 class CAHInitImportCharacter : public IActionHandler
3457 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3459 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3460 if (!list)
3462 nlwarning("element " GROUP_LIST_CHARACTER " not found probably bad outgame.xml");
3463 return;
3466 // retrieve saved files
3467 std::vector<string> savedCharacters;
3468 CPath::getPathContent("save/", false, false, true, savedCharacters);
3470 CInterfaceGroup *newLine;
3471 CInterfaceGroup *prevLine = NULL;
3473 for (uint i = 0; i < savedCharacters.size(); ++i)
3475 // search saved characters only
3476 if (testWildCard(CFile::getFilename(savedCharacters[i]), "character_*.save"))
3478 const std::string id = CFile::getFilenameWithoutExtension(savedCharacters[i]).substr(strlen("character_"));
3479 if (id.empty())
3480 continue;
3482 std::vector<pair<string, string>> params;
3483 params.clear();
3484 params.push_back(std::pair<string, string>("id", id));
3485 // adjust ref
3486 if (list->getNumGroup() > 0)
3487 params.push_back(std::pair<string, string>("posref", "BL TL"));
3489 newLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_import", GROUP_LIST_CHARACTER, params);
3490 if (newLine)
3492 CViewText *text = dynamic_cast<CViewText*>(newLine->getView("name"));
3493 if (text)
3494 text->setText(string(savedCharacters[i]));
3496 // first button is pushed
3497 CCtrlButton *button = dynamic_cast<CCtrlButton*>(newLine->getCtrl("but"));
3498 if (button && list->getNumGroup() == 0)
3499 button->setPushed(true);
3501 // add to the list now
3502 newLine->setParent(list);
3503 newLine->setParentSize(list);
3504 newLine->setParentPos(prevLine);
3506 list->addGroup(newLine);
3508 prevLine = newLine;
3512 // none case
3513 if (list->getNumGroup() == 0)
3514 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(3)");
3516 list->invalidateCoords();
3519 REGISTER_ACTION_HANDLER( CAHInitImportCharacter, "import_char_init" );
3521 // ***************************************************************************
3522 class CAHResetImportCharacter : public IActionHandler
3524 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3526 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3527 if (list)
3528 list->clearGroups();
3530 if (!ImportCharacter.empty())
3531 ImportCharacter = "";
3534 REGISTER_ACTION_HANDLER( CAHResetImportCharacter, "import_char_reset" );
3536 // ***************************************************************************
3537 class CAHSelectImportCharacter : public IActionHandler
3539 virtual void execute (CCtrlBase *pCaller, const std::string &Params)
3541 struct CUnpush : public CInterfaceElementVisitor
3543 CCtrlBase *Ref;
3544 virtual void visitCtrl(CCtrlBase *ctrl)
3546 if (ctrl == Ref) return;
3547 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(ctrl);
3548 if (but)
3550 but->setPushed(false);
3554 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3555 if (!list)
3556 return;
3558 // unselect
3559 if (Params.empty())
3561 CUnpush unpusher;
3562 unpusher.Ref = pCaller;
3563 list->visit(&unpusher);
3566 // now select
3567 std::string name;
3568 if (Params.empty())
3570 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pCaller);
3571 if (!pCB)
3572 return;
3574 std::string id = pCB->getId();
3575 id = id.substr(0, id.rfind(':'));
3577 if (!fromString(id.substr(id.rfind(':')+1, id.size()), name))
3578 return;
3580 pCB->setPushed(true);
3582 else
3583 if (!fromString(Params, name))
3584 return;
3586 ImportCharacter = "";
3587 // check filename and store
3588 if (CFile::fileExists(toString("save/character_%s.save", name.c_str())))
3589 ImportCharacter = name;
3592 REGISTER_ACTION_HANDLER( CAHSelectImportCharacter, "import_char_select" );
3594 // ***************************************************************************
3595 class CAHImportCharacter : public IActionHandler
3597 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3599 if (ImportCharacter.empty())
3600 return;
3602 if (!CFile::fileExists(toString("save/character_%s.save", ImportCharacter.c_str())))
3603 return;
3605 bool success = false;
3607 CIFile fd;
3608 CCharacterSummary CS;
3609 // use temporary file until close()
3610 if (fd.open(toString("save/character_%s.save", ImportCharacter.c_str())))
3614 CS.serial(fd);
3615 SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", CS);
3617 // validate import
3618 CDBManager::getInstance()->getDbProp("UI:TEMP:IMPORT")->setValue32(1);
3619 success = true;
3621 catch (const EStream &e)
3623 nlwarning(e.what());
3625 fd.close();
3627 else
3628 nlwarning("Failed to open file: save/character_%s.save", ImportCharacter.c_str());
3630 // user notification
3631 if (!success)
3632 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(2)");
3633 else
3634 CAHManager::getInstance()->runActionHandler("proc", NULL, "proc_charsel_create_new");
3637 REGISTER_ACTION_HANDLER( CAHImportCharacter, "import_char" );
3639 // ***************************************************************************
3640 class CAHExportCharacter : public IActionHandler
3642 virtual void execute (CCtrlBase * /* pCaller */, const std::string &Params)
3644 if (Params.empty())
3645 return;
3647 sint32 slot = -1;
3648 if (!fromString(getParam(Params, "slot"), slot))
3649 return;
3651 if (slot >= CharacterSummaries.size() || slot < 0)
3652 return;
3654 // retrieve infos
3655 CCharacterSummary &CS = CharacterSummaries[slot];
3656 if (CS.Name.empty())
3657 return;
3659 // extract name
3660 const std::string name = buildPlayerNameForSaveFile(CS.Name.toUtf8());
3662 COFile fd;
3663 bool success = false;
3664 // use temporary file until close()
3665 if (fd.open(toString("save/character_%s.save", name.c_str()), false, false, true))
3669 fd.serial(CS);
3670 fd.flush();
3671 // validate
3672 success = true;
3674 catch (const EStream &e)
3676 nlwarning(e.what());
3678 fd.close();
3680 else
3681 nlwarning("Failed to open file: save/character_%s.save", name.c_str());
3683 const uint8 val = (success == true) ? 0 : 1;
3684 // user notification
3685 CLuaManager::getInstance().executeLuaScript(toString("outgame:procCharselNotifaction(%i)", val));
3688 REGISTER_ACTION_HANDLER( CAHExportCharacter, "export_char" );