Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / connection.cpp
blob10b38e8829c13f4487b10dab46dbdb9e2959b89d
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2021 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 #include "nel/misc/stream.h"
37 // 3D Interface.
38 #include "nel/3d/u_driver.h"
39 #include "nel/3d/u_text_context.h"
40 #include "nel/3d/stereo_display.h"
41 // Game Share
42 //#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE
43 #include "game_share/gender.h"
44 #include "game_share/character_summary.h"
45 #include "game_share/roles.h"
46 #include "game_share/character_title.h"
47 #include "game_share/shard_names.h"
48 #include "game_share/utils.h"
49 #include "game_share/bg_downloader_msg.h"
51 // Std.
52 #include <vector>
53 // Client
54 #include "connection.h"
55 #include "nel/gui/action_handler.h"
56 #include "sound_manager.h"
57 #include "input.h"
58 #include "login.h"
59 #include "login_progress_post_thread.h"
61 #include "client_cfg.h"
62 #include "actions_client.h"
63 #include "user_entity.h"
64 #include "time_client.h"
65 #include "net_manager.h"
66 #include "string_manager_client.h"
67 #include "far_tp.h"
68 #include "movie_shooter.h"
70 // Interface part
71 #include "interface_v3/interface_manager.h"
72 #include "interface_v3/character_3d.h"
73 #include "nel/gui/ctrl_button.h"
74 #include "interface_v3/input_handler_manager.h"
75 #include "nel/gui/group_editbox.h"
76 #include "nel/gui/interface_expr.h"
77 #include "init_main_loop.h"
78 #include "continent_manager.h"
79 #include "interface_v3/group_quick_help.h"
80 #include "nel/gui/dbgroup_combo_box.h"
82 #include "r2/dmc/client_edition_module.h"
83 #include "r2/editor.h"
84 #include "game_share/scenario.h"
85 #include "session_browser_impl.h"
87 #include "bg_downloader_access.h"
88 #include "main_loop.h"
90 #include "misc.h"
93 ////////////////
94 // Namespaces //
95 ////////////////
96 using namespace NLMISC;
97 using namespace NL3D;
98 using namespace NLNET;
99 using namespace std;
100 using namespace RSMGR;
101 using namespace R2;
105 /////////////
106 // Externs //
107 /////////////
108 extern uint32 Version; // Client Version.
109 extern UDriver *Driver;
110 extern UTextContext *TextContext;
111 extern bool game_exit;
113 extern CSoundManager *SoundMngr;
115 extern bool serverReceivedReady;
116 extern CContinentManager ContinentMngr;
118 extern bool MovieShooterSaving;
119 extern void endMovieShooting();
120 extern void replayMovieShooting();
121 extern void saveMovieShooting();
122 extern void displaySpecialTextProgress(const char *text);
123 extern bool InitMouseWithCursor(bool hardware);
125 extern bool SetMousePosFirstTime;
127 /////////////
128 // Globals // initialization occurs in the function : connection
129 /////////////
130 bool userChar;
131 bool noUserChar;
132 bool ConnectInterf;
133 bool CreateInterf;
134 bool CharacterInterf;
135 TTime UniversalTime;
136 std::vector<CCharacterSummary> CharacterSummaries;
137 std::string UsedFSAddr;
138 std::string UserPrivileges;
139 uint8 ServerPeopleActive = 255;
140 uint8 ServerCareerActive = 255;
142 bool WaitServerAnswer;
143 bool CharNameValidArrived;
144 bool CharNameValid;
145 string CharNameValidDBLink;
146 uint8 PlayerSelectedSlot = 0;
147 string PlayerSelectedFileName;
148 TSessionId PlayerSelectedMainland= (TSessionId)0; // This is the mainland selected at the SELECT perso!!
149 std::string PlayerSelectedHomeShardName;
150 std::string PlayerSelectedHomeShardNameWithParenthesis;
151 extern std::string CurrentCookie;
153 std::string NewKeysCharNameWanted; // name of the character for which a new keyset must be created
154 std::string NewKeysCharNameValidated;
155 std::string GameKeySet = "keys.xml";
156 std::string RingEditorKeySet = "keys_r2ed.xml";
158 string ScenarioFileName;
159 sint LoginCharsel = -1;
161 std::string ImportCharacter;
163 static const char *KeySetVarName = "BuiltInKeySets";
165 #define GROUP_LIST_CHARACTER "ui:outgame:charsel_import:import_list"
166 #define GROUP_LIST_MAINLAND "ui:outgame:appear_mainland:mainland_list"
167 #define GROUP_LIST_KEYSET "ui:outgame:appear_keyset:keyset_list"
168 vector<CMainlandSummary> Mainlands;
169 TSessionId MainlandSelected = (TSessionId)0; // This is the mainland selected at the CREATE perso!!
171 // This is the home session (mainland) of the selected character
172 TSessionId CharacterHomeSessionId = (TSessionId)0;
175 bool PatchBegun = false;
177 // \todo GUIGUI : USE TRANSPORT CLASS.
178 // SVersionAnswer versionAnswer;
181 // Finite State Machine : all the states before entering the game
182 // ------------------------------------------------------------------------------------------------
183 TInterfaceState globalMenu();
186 bool hasPrivilegeDEV() { return (UserPrivileges.find(":DEV:") != std::string::npos); }
187 bool hasPrivilegeSGM() { return (UserPrivileges.find(":SGM:") != std::string::npos); }
188 bool hasPrivilegeGM() { return (UserPrivileges.find(":GM:") != std::string::npos); }
189 bool hasPrivilegeVG() { return (UserPrivileges.find(":VG:") != std::string::npos); }
190 bool hasPrivilegeSG() { return (UserPrivileges.find(":SG:") != std::string::npos); }
191 bool hasPrivilegeG() { return (UserPrivileges.find(":G:") != std::string::npos); }
192 bool hasPrivilegeEM() { return (UserPrivileges.find(":EM:") != std::string::npos); }
193 bool hasPrivilegeEG() { return (UserPrivileges.find(":EG:") != std::string::npos); }
194 bool hasPrivilegeOBSERVER() { return (UserPrivileges.find(":OBSERVER:") != std::string::npos); }
195 bool hasPrivilegeTESTER() { return (UserPrivileges.find(":TESTER:") != std::string::npos); }
198 // Restore the video mode (fullscreen for example) after the connection (done in a window)
199 void connectionRestoreVideoMode ()
201 if (StereoDisplay)
202 StereoDisplayAttached = StereoDisplay->attachToDisplay();
204 // And setup hardware mouse if we have to
205 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached);
206 SetMouseFreeLook ();
207 SetMouseCursor ();
208 SetMouseSpeed (ClientCfg.CursorSpeed);
209 SetMouseAcceleration (ClientCfg.CursorAcceleration);
211 // Restore user UI scaling
212 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
216 #define UI_VARIABLES_SCREEN_WEBSTART 8
219 // ***************************************************************************
220 // Called to reload the start test page in test browser mode
221 class CAHOnReloadTestPage: public IActionHandler
223 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
225 CInterfaceManager *pIM = CInterfaceManager::getInstance();
226 // need to reset password and current screen
227 CGroupHTML *pGH = dynamic_cast<CGroupHTML*>(CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER));
229 pGH->browse(ClientCfg.TestBrowserUrl.c_str());
233 REGISTER_ACTION_HANDLER (CAHOnReloadTestPage, "on_reload_test_page");
236 // ------------------------------------------------------------------------------------------------
237 void setOutGameFullScreen()
239 if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1)
241 if (StereoDisplayAttached)
242 StereoDisplay->detachFromDisplay();
243 StereoDisplayAttached = false;
245 InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached);
248 // Enable auto scaling in login window
249 CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
252 // ------------------------------------------------------------------------------------------------
253 class CSoundGlobalMenu
255 public:
256 CSoundGlobalMenu()
258 _MusicWantedAsync= false;
259 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
261 void reset();
262 void setMusic(const string &music, bool async);
263 void updateSound();
264 private:
265 string _MusicPlayed;
266 string _MusicWanted;
267 bool _MusicWantedAsync;
268 sint _NbFrameBeforeChange;
269 enum {NbFrameBeforeChangeMax= 10};
272 void CSoundGlobalMenu::reset()
274 _MusicPlayed.clear();
275 _MusicWanted.clear();
278 void CSoundGlobalMenu::updateSound()
280 // **** update the music played
281 // The first music played is the music played at loading, before select char
282 if (_MusicPlayed.empty())
283 _MusicPlayed = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
284 if (_MusicWanted.empty())
285 _MusicWanted = toLowerAscii(LoadingMusic.empty() ? ClientCfg.StartMusic : LoadingMusic);
287 // because music is changed when the player select other race for instance,
288 // wait the 3D to load (stall some secs)
290 // if the wanted music is the same as the one currently playing, just continue playing
291 if(_MusicPlayed!=_MusicWanted)
293 // wait nbFrameBeforeChangeMax before actually changing the music
294 _NbFrameBeforeChange--;
295 if(_NbFrameBeforeChange<=0)
297 _MusicPlayed= _MusicWanted;
298 // play the music
299 if (SoundMngr != NULL)
300 SoundMngr->playMusic(_MusicPlayed, 500, _MusicWantedAsync, true, true);
305 // **** update mngr
306 if (SoundMngr != NULL)
307 SoundMngr->update();
310 void CSoundGlobalMenu::setMusic(const string &music, bool async)
312 _MusicWanted= toLowerAscii(music);
313 _MusicWantedAsync= async;
314 // reset the counter
315 _NbFrameBeforeChange= NbFrameBeforeChangeMax;
317 static CSoundGlobalMenu SoundGlobalMenu;
320 // New version of the menu after the server connection
322 // If you add something in this function, check CFarTP,
323 // some kind of reinitialization might be useful over there.
324 // ------------------------------------------------------------------------------------------------
325 bool connection (const string &cookie, const string &fsaddr)
328 NLMISC::TTime connStart = ryzomGetLocalTime();
329 NLMISC::TTime connLast = connStart;
330 NLMISC::TTime connCurrent = connLast;
332 game_exit = false;
334 // set resolution from cfg after login
335 connectionRestoreVideoMode ();
337 // Preload continents
339 const string nmsg("Loading continents...");
340 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
341 ContinentMngr.preloadSheets();
343 connLast = connCurrent;
344 connCurrent = ryzomGetLocalTime();
345 nlinfo ("PROFILE: %d seconds (%d total) for Loading continents", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
348 if (!fsaddr.empty () && !cookie.empty ())
350 // it means that we have a nel_launcher values, so we are online
351 ClientCfg.Local = 0;
352 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
355 CInterfaceManager *pIM = CInterfaceManager::getInstance();
357 // If the Client is in in Local Mode -> init the Time and return.
358 if (ClientCfg.Local)
360 #ifdef ENABLE_INCOMING_MSG_RECORDER
361 NetMngr.init("", "");
362 // Set the impulse callback.
363 NetMngr.setImpulseCallback (impulseCallBack);
364 // Set the database.
365 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
366 // init the string manager cache.
367 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
368 #endif
369 return true;
372 ProgressBar.setFontFactor(1.0f);
374 // Init out game
375 setOutGameFullScreen();
377 string nmsg("Initializing outgame...");
378 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
379 pIM->initOutGame();
381 connLast = connCurrent;
382 connCurrent = ryzomGetLocalTime();
383 nlinfo ("PROFILE: %d seconds (%d total) for Initializing outgame", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
385 // Init user interface
386 nmsg = "Initializing user interface...";
387 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
389 // Hide cursor for interface
390 //Driver->showCursor (false);
392 // Init global variables
393 userChar = false;
394 noUserChar = false;
395 ConnectInterf = true;
396 CreateInterf = true;
397 CharacterInterf = true;
398 WaitServerAnswer= false;
400 FarTP.setOutgame();
402 // Start the finite state machine
403 static bool firstConnection = true;
404 TInterfaceState InterfaceState = AUTO_LOGIN;
405 // TInterfaceState InterfaceState = firstConnection ? AUTO_LOGIN : GLOBAL_MENU;
406 /*if (!firstConnection)
408 noUserChar = userChar = false;
409 WaitServerAnswer = true;
412 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(ClientCfg.Local ? 6 : -1); // TMP TMP
413 IngameDbMngr.flushObserverCalls();
414 NLGUI::CDBManager::getInstance()->flushObserverCalls();
416 // Active inputs
417 Actions.enable(true);
418 EditActions.enable(true);
420 if (ClientCfg.SelectCharacter == -1)
422 // not initialized at login and remain hardware until here ...
424 // Re-initialise the mouse (will be now in hardware mode, if required)
425 //InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
427 // no ui init if character selection is automatic
428 //SetMouseFreeLook ();
429 //SetMouseCursor ();
430 SetMouseSpeed (ClientCfg.CursorSpeed);
431 SetMouseAcceleration (ClientCfg.CursorAcceleration);
433 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
434 PlayerSelectedSlot = ClientCfg.SelectedSlot;
437 connLast = connCurrent;
438 connCurrent = ryzomGetLocalTime();
439 nlinfo ("PROFILE: %d seconds (%d total) for Initializing user interface", (uint32)(connCurrent-connLast)/1000, (uint32)(connCurrent-connStart)/1000);
441 nlinfo ("PROFILE: %d seconds for connection", (uint32)(ryzomGetLocalTime ()-connStart)/1000);
443 // Init web box
445 // TMP TMP
446 if (ClientCfg.Local)
448 InterfaceState = GLOBAL_MENU;
451 // No loading music here, this is right before character selection, using the existing music
453 // Create the loading texture. We can't do that before because we need to add search path first.
454 beginLoading (LoadBackground);
455 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
457 while ((InterfaceState != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
459 switch (InterfaceState)
461 case AUTO_LOGIN:
462 InterfaceState = autoLogin (cookie, fsaddr, firstConnection);
463 break;
465 case GLOBAL_MENU:
466 if (!ClientCfg.Local)
468 if (ClientCfg.SelectCharacter == -1)
470 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
473 InterfaceState = globalMenu();
474 break;
475 case GOGOGO_IN_THE_GAME:
476 break;
477 case QUIT_THE_GAME:
478 break;
482 firstConnection = false;
484 // Restore user UI scaling
485 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
487 // Disable inputs
488 Actions.enable(false);
489 EditActions.enable(false);
491 // resetTextContext ("ingame.ttf", true);
492 resetTextContext ("ryzom.ttf", true);
494 if (InterfaceState == GOGOGO_IN_THE_GAME)
496 // set background downloader to 'paused' to ease loading of client
497 #ifdef RYZOM_BG_DOWNLOADER
498 pauseBGDownloader();
499 #endif
500 return true;
503 if (InterfaceState == QUIT_THE_GAME)
504 return false;
505 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
506 return true;
512 // Allow user to reselect character after the server reconnection
513 // ------------------------------------------------------------------------------------------------
514 bool reconnection()
517 game_exit = false;
519 setOutGameFullScreen();
521 // Preload continents
523 const string nmsg ("Loading continents...");
524 ProgressBar.newMessage (ClientCfg.buildLoadingString(nmsg) );
525 ContinentMngr.preloadSheets();
528 if (!fsaddr.empty () && !cookie.empty ())
530 // it means that we have a nel_launcher values, so we are online
531 ClientCfg.Local = 0;
532 nlinfo ("Using the nel launcher parameters '%s' '%s'", cookie.c_str (), fsaddr.c_str ());
535 // If the Client is in in Local Mode -> init the Time and return.
536 if (ClientCfg.Local)
538 #ifdef ENABLE_INCOMING_MSG_RECORDER
539 NetMngr.init("", "");
540 // Set the impulse callback.
541 NetMngr.setImpulseCallback (impulseCallBack);
542 // Set the database.
543 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
544 // init the string manager cache.
545 STRING_MANAGER::CStringManagerClient::instance()->initCache("", ClientCfg.LanguageCode); // VOIR BORIS
546 #endif
547 connectionRestoreVideoMode ();
548 return true;
552 CInterfaceManager *pIM = CInterfaceManager::getInstance();
554 ProgressBar.setFontFactor(1.0f);
556 // Init out game
557 SoundGlobalMenu.reset();
558 pIM->initOutGame();
560 // Hide cursor for interface
561 Driver->showCursor (false);
563 // Init global variables
564 userChar = false;
565 noUserChar = false;
566 ConnectInterf = true;
567 CreateInterf = true;
568 CharacterInterf = true;
569 WaitServerAnswer= false;
571 FarTP.setOutgame();
573 if (SoundMngr)
574 SoundMngr->setupFadeSound(1.0f, 1.0f);
576 // these two globals sequence GlobalMenu to display the character select dialog
577 WaitServerAnswer = true;
578 userChar = true;
580 // Start the finite state machine
581 TInterfaceState InterfaceState = GLOBAL_MENU;
583 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(-1);
584 IngameDbMngr.flushObserverCalls();
585 NLGUI::CDBManager::getInstance()->flushObserverCalls();
587 // Active inputs
588 Actions.enable(true);
589 EditActions.enable(true);
591 if (ClientCfg.SelectCharacter == -1)
593 // Re-initialise the mouse (will be now in hardware mode, if required)
594 SetMousePosFirstTime = true;
595 InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup
597 // no ui init if character selection is automatic
598 SetMouseFreeLook ();
599 SetMouseCursor ();
600 SetMouseSpeed (ClientCfg.CursorSpeed);
601 SetMouseAcceleration (ClientCfg.CursorAcceleration);
602 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(ClientCfg.SelectedSlot);
603 PlayerSelectedSlot = ClientCfg.SelectedSlot;
606 // we want the teleport graphics to display (not like in Server Hop mode)
607 // this also kicks the state machine to sendReady() so we stop spinning in farTPmainLoop
608 FarTP.setIngame();
610 // Not loading music here, this is before character selection, keep existing music
612 // Create the loading texture. We can't do that before because we need to add search path first.
613 beginLoading (LoadBackground);
614 UseEscapeDuringLoading = USE_ESCAPE_DURING_LOADING;
616 // character selection menu
617 while( InterfaceState == GLOBAL_MENU ) // != GOGOGO_IN_THE_GAME) && (InterfaceState != QUIT_THE_GAME))
619 if (ClientCfg.SelectCharacter == -1)
621 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(0); // 0 == select
623 InterfaceState = globalMenu();
626 // Restore user UI scaling
627 CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
629 // Disable inputs
630 Actions.enable(false);
631 EditActions.enable(false);
633 // resetTextContext ("ingame.ttf", true);
634 resetTextContext ("ryzom.ttf", true);
636 if (InterfaceState == GOGOGO_IN_THE_GAME)
638 #ifdef RYZOM_BG_DOWNLOADER
639 pauseBGDownloader();
640 #endif
641 return true;
643 if (InterfaceState == QUIT_THE_GAME)
644 return false;
645 nlassert ((InterfaceState == GOGOGO_IN_THE_GAME) || (InterfaceState == QUIT_THE_GAME));
646 return true;
649 // Automatic connection to the server, the user can't do anything
650 // ------------------------------------------------------------------------------------------------
651 TInterfaceState autoLogin (const string &cookie, const string &fsaddr, bool firstConnection)
653 noUserChar = userChar = false;
654 string defaultPort = string(":47851");
655 if(!fsaddr.empty())
657 // If we have a front end address from command line, use this one
658 UsedFSAddr = fsaddr;
659 if (UsedFSAddr.find(":") == string::npos)
661 UsedFSAddr += defaultPort;
664 else
666 // Otherwise, use the front end address from configfile
667 UsedFSAddr = ClientCfg.FSHost;
668 FSAddr = UsedFSAddr; // to be able to do /reconnect
669 LoginSM.pushEvent( CLoginStateMachine::ev_skip_all_login );
670 if (UsedFSAddr.find(":") == string::npos)
672 UsedFSAddr += defaultPort;
673 FSAddr += defaultPort; // to be able to do /reconnect
677 if (firstConnection)
678 NetMngr.init (cookie, UsedFSAddr);
680 // Connection
681 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
683 string result;
685 if (firstConnection)
687 NetMngr.connect (result);
689 if (!result.empty())
691 nlerror ("connection : %s.", result.c_str());
692 return QUIT_THE_GAME;
695 // Ok the client is connected
697 // Set the impulse callback.
698 NetMngr.setImpulseCallback (impulseCallBack);
699 // Set the database.
700 NetMngr.setDataBase (IngameDbMngr.getNodePtr());
702 // init the string manager cache.
703 STRING_MANAGER::CStringManagerClient::instance()->initCache(UsedFSAddr, ClientCfg.LanguageCode);
706 else
708 CCharacterSummary cs;
709 cs.Name = "babar";
710 //cs.Surname = "l'elephant";
711 cs.People = EGSPD::CPeople::Zorai;
712 cs.VisualPropA.PropertySubData.Sex = 0; // Male
713 //Deprecated
714 // cs.Role = ROLES::range_warrior;
715 // cs.Job = JOBS::CasterBuffer;
716 // cs.JobLevel = 16;
717 CharacterSummaries.push_back(cs);
719 cs.Name = "yeah";
720 //cs.Surname = "zeelot";
721 cs.People = EGSPD::CPeople::Matis;
722 cs.VisualPropA.PropertySubData.Sex = 1; // Female
723 //Deprecated
724 // cs.Role = ROLES::buffer_magician;
725 // cs.Job = JOBS::CasterHealer;
726 // cs.JobLevel = 8;
727 CharacterSummaries.push_back(cs);
729 userChar = true;
732 WaitServerAnswer = true;
734 return GLOBAL_MENU;
737 // ------------------------------------------------------------------------------------------------
738 void globalMenuMovieShooter()
741 if(MovieShooterSaving)
743 // Add the buffer frame to the movie.
744 if(!MovieShooter.addFrame(TimeInSec, Driver))
746 // Fail to add the frame => abort.
747 endMovieShooting();
749 else
751 // Ok, just add a display.
752 displaySpecialTextProgress("MovieShooting");
758 // ------------------------------------------------------------------------------------------------
759 // Build a valid PlayerName for file Save selection.
760 std::string buildPlayerNameForSaveFile(const std::string &playerNameIn)
762 // remove any shard name appended
763 string playerName = playerNameIn;
764 string::size_type pos = playerNameIn.find('(');
765 if(pos!=string::npos && pos>0)
767 playerName.resize(pos);
770 // replace any special ucchar with '_'
771 string ret;
772 ret.resize(playerName.size());
773 for(uint i=0;i<playerName.size();i++)
775 ucchar c= playerName[i];
776 if( (c>='A' && c<='Z') ||
777 (c>='a' && c<='z') ||
778 (c>='0' && c<='9') ||
779 (c=='_') )
781 ret[i]= tolower(c); // TODO: toLowerAscii
783 else
784 ret[i]= '_';
786 return ret;
790 #ifdef RYZOM_BG_DOWNLOADER
791 static bool LuaBGDSuccessFlag = true; // tmp, for debug
793 void updateBGDownloaderUI()
795 CInterfaceManager *im = CInterfaceManager::getInstance();
796 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
797 bool bgWindowVisible = true;
798 if (im->isInGame())
800 static NLMISC::CRefPtr<CInterfaceElement> bgDownloaderWindow;
801 if (!bgDownloaderWindow)
803 bgDownloaderWindow = CWidgetManager::getInstance()->getElementFromId("ui:interface:bg_downloader");
805 bgWindowVisible = bgDownloaderWindow && bgDownloaderWindow->getActive();
807 bool prevSuccess = LuaBGDSuccessFlag;
808 if (isBGDownloadEnabled() && PatchBegun)
810 if (AvailablePatchs == 0)
812 if (LuaBGDSuccessFlag)
814 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
817 else
819 switch(bgDownloader.getLastTaskResult())
821 case BGDownloader::TaskResult_Unknown:
823 float progress = 0.f;
824 /*if (bgDownloader.getTotalSize() != 0)
826 progress = (float) bgDownloader.getPatchingSize() / bgDownloader.getTotalSize();
828 if (bgDownloader.getTotalFilesToGet() != 0)
830 progress = (bgDownloader.getCurrentFilesToGet() + bgDownloader.getCurrentFileProgress()) / bgDownloader.getTotalFilesToGet();
832 if (LuaBGDSuccessFlag && bgWindowVisible)
834 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript(toString("bgdownloader:setPatchProgress(%f)", progress));
836 // display current priority of the downloader
837 if (LuaBGDSuccessFlag && bgWindowVisible)
839 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:displayPriority()");
842 break;
843 case BGDownloader::TaskResult_Success:
844 if (LuaBGDSuccessFlag && bgWindowVisible)
846 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchSuccess()");
848 // task finished
849 AvailablePatchs = 0;
850 if (bgDownloader.getPatchCompletionFlag(true /* clear flag */))
852 // when in-game, display a message to signal the end of the patch
853 if (im->isInGame())
855 im->displaySystemInfo(CI18N::get("uiBGD_InGamePatchCompletion"), "BC");
858 break;
859 default:
860 // error case
861 if (LuaBGDSuccessFlag && bgWindowVisible)
863 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setPatchError()");
865 break;
869 else
871 if (LuaBGDSuccessFlag && bgWindowVisible)
873 if (isBGDownloadEnabled())
875 // no necessary patch for now
876 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoNecessaryPatch()");
878 else
880 // no download ui
881 LuaBGDSuccessFlag = CLuaManager::getInstance().executeLuaScript("bgdownloader:setNoDownloader()");
885 if (prevSuccess != LuaBGDSuccessFlag)
887 nlwarning("Some scipt error occurred");
890 #endif
892 // compute patcher priority, depending on the presence of one or more mainland characters : in this case, give the patch a boost
893 void updatePatcherPriorityBasedOnCharacters()
895 #ifdef RYZOM_BG_DOWNLOADER
896 if (isBGDownloadEnabled())
898 if (CBGDownloaderAccess::getInstance().getDownloadThreadPriority() != BGDownloader::ThreadPriority_Paused)
900 // choose priority based on available characters :
901 bool hasMainlandChar = false;
902 for(std::vector<CCharacterSummary>::iterator it = CharacterSummaries.begin(); it != CharacterSummaries.end(); ++it)
904 if (it->Name.empty()) continue;
905 if (!it->InNewbieland)
907 hasMainlandChar = true;
908 break;
911 CBGDownloaderAccess::getInstance().requestDownloadThreadPriority(hasMainlandChar ? BGDownloader::ThreadPriority_Normal : BGDownloader::ThreadPriority_Low, false);
914 #endif
917 // Launch the interface to choose a character
918 // ------------------------------------------------------------------------------------------------
919 TInterfaceState globalMenu()
921 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_CharacterSelection, "login_step_character_selection"));
923 #ifdef RYZOM_BG_DOWNLOADER
924 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
926 if (isBGDownloadEnabled())
928 // If there's a need for mainland download, then proceed
929 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
931 // if a task is already started, then this was a situation where player went back from game to the character selection,
932 // so just unpause
933 BGDownloader::TTaskResult dummyResult;
934 ucstring dummyMessage; // OLD
935 if (!bgDownloader.isTaskEnded(dummyResult, dummyMessage))
937 unpauseBGDownloader();
941 #endif
943 CInterfaceManager *pIM = CInterfaceManager::getInstance();
945 sint32 nScreenConnecting, nScreenIntro, nScreenServerCrashed;
946 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_connecting"), nScreenConnecting);
947 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_intro"), nScreenIntro);
948 fromString(CWidgetManager::getInstance()->getParser()->getDefine("screen_crashing"), nScreenServerCrashed);
950 // SKIP INTRO : Write to the database if we have to skip the intro and write we want to skip further intro to client cfg
951 if (ClientCfg.SkipIntro)
953 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:SKIP_INTRO", false);
954 if (pNL != NULL)
955 pNL->setValue64(1);
958 TGameCycle serverTick = NetMngr.getCurrentServerTick();
959 bool PlayerWantToGoInGame = false;
960 bool firewallTimeout = false;
962 ProgressBar.finish(); // no progress while selecting character
964 while (PlayerWantToGoInGame == false)
967 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
968 // tmp for debug
969 if (::GetAsyncKeyState(VK_SPACE))
971 pIM->uninitOutGame();
972 pIM->initOutGame();
973 CWidgetManager::getInstance()->activateMasterGroup ("ui:outgame", true);
974 NLGUI::CDBManager::getInstance()->getDbProp ("UI:CURRENT_SCREEN")->setValue32(2); // TMP TMP
975 IngameDbMngr.flushObserverCalls();
976 NLGUI::CDBManager::getInstance()->flushObserverCalls();
977 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(false);
978 CWidgetManager::getInstance()->getElementFromId("ui:outgame:charsel")->setActive(true);
979 // Active inputs
980 Actions.enable(true);
981 EditActions.enable(true);
982 LuaBGDSuccessFlag = true;
983 CWidgetManager::getInstance()->getParser()->reloadAllLuaFileScripts();
985 #endif
987 #ifdef RYZOM_BG_DOWNLOADER
988 updateBGDownloaderUI();
989 #endif
991 // Update network.
994 if ( ! firewallTimeout )
995 NetMngr.update();
997 catch (const EBlockedByFirewall&)
999 if ( NetMngr.getConnectionState() == CNetManager::Disconnect )
1001 firewallTimeout = true;
1003 else
1005 // Display the firewall alert string
1006 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:connecting:title"));
1007 if (pVT != NULL)
1008 pVT->setTextLocalized("uiFirewallAlert", true);
1010 // The mouse and fullscreen mode should be unlocked for the user to set the firewall permission
1011 nlSleep( 30 ); // 'nice' the client, and prevent to make too many send attempts
1015 IngameDbMngr.flushObserverCalls();
1016 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1018 // check if we can send another dated block
1019 if (NetMngr.getCurrentServerTick() != serverTick)
1022 serverTick = NetMngr.getCurrentServerTick();
1023 NetMngr.send(serverTick);
1025 else
1027 // Send dummy info
1028 NetMngr.send();
1030 // Update the DT T0 and T1 global variables
1031 updateClientTime();
1032 CInputHandlerManager::getInstance()->pumpEvents();
1033 Driver->clearBuffers(CRGBA::Black);
1034 Driver->setMatrixMode2D11();
1036 // Update sound
1037 SoundGlobalMenu.updateSound();
1039 // Interface handling & displaying (processes clicks...)
1040 pIM->updateFrameEvents();
1041 pIM->updateFrameViews(NULL);
1042 IngameDbMngr.flushObserverCalls();
1043 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1045 // Movie shooter
1046 globalMenuMovieShooter();
1048 // Force the client to sleep a bit.
1049 if(ClientCfg.Sleep >= 0)
1051 nlSleep(ClientCfg.Sleep);
1054 #if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) && 0
1055 if (::GetAsyncKeyState(VK_CONTROL))
1057 pIM->displayUIViewBBoxs("");
1058 pIM->displayUICtrlBBoxs("");
1059 pIM->displayUIGroupBBoxs("");
1060 displayDebugUIUnderMouse();
1062 #endif
1064 // Display
1065 Driver->swapBuffers();
1067 // SERVER INTERACTIONS WITH INTERFACE
1068 if (WaitServerAnswer)
1070 if (noUserChar || userChar)
1072 #ifdef RYZOM_BG_DOWNLOADER
1073 if (isBGDownloadEnabled())
1075 // If there's a need for mainland download, then proceed
1076 if (AvailablePatchs & (1 << BGDownloader::DownloadID_MainLand))
1078 // if a task is already started, then this was a situation where player went back from game to the character selection,
1079 // so just unpause
1080 BGDownloader::TTaskResult dummyResult;
1081 ucstring dummyMessage; // OLD
1082 if (bgDownloader.isTaskEnded(dummyResult, dummyMessage))
1084 // launch mainland patch as a background task
1085 BGDownloader::CTaskDesc task(BGDownloader::DLState_GetAndApplyPatch,
1086 (1 << BGDownloader::DownloadID_MainLand));
1087 bgDownloader.startTask(task, getBGDownloaderCommandLine(), false /* showDownloader */);
1089 // choose priority based on available characters :
1090 updatePatcherPriorityBasedOnCharacters();
1092 PatchBegun = true;
1096 #endif
1098 //nlinfo("impulseCallBack : received userChars list");
1099 noUserChar = userChar = false;
1100 if( FarTP.isReselectingChar() || !FarTP.isServerHopInProgress() ) // if doing a Server Hop, expect serverReceivedReady without action from the user
1102 sint charSelect = -1;
1103 if (ClientCfg.SelectCharacter != -1)
1104 charSelect = ClientCfg.SelectCharacter;
1106 if (LoginCharsel != -1)
1107 charSelect = LoginCharsel;
1109 WaitServerAnswer = false;
1110 if (charSelect == -1 || FarTP.isReselectingChar())
1112 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_CHARS", false);
1113 if (pNL != NULL)
1115 pNL->setValue64 (1); // Send impulse to interface observers
1116 IngameDbMngr.flushObserverCalls();
1117 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1118 pNL->setValue64 (0);
1119 IngameDbMngr.flushObserverCalls();
1120 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1123 else
1125 // check that the pre selected character is available
1126 if (CharacterSummaries[charSelect].People == EGSPD::CPeople::Unknown || charSelect > 4)
1128 // BAD ! preselected char does not exist, use the first available or fail
1129 uint i;
1130 for (i=0; i<CharacterSummaries.size(); ++i)
1132 if (CharacterSummaries[i].People != EGSPD::CPeople::Unknown)
1133 break;
1135 if (i == CharacterSummaries.size())
1137 Driver->systemMessageBox("You have no character for the current user.\nClient will exit.", "Char loading error", UDriver::okType, UDriver::exclamationIcon);
1138 exit(-1);
1140 else
1142 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);
1143 if (ret == UDriver::noId)
1144 exit(-1);
1145 else
1146 charSelect = i;
1149 // Auto-selection for fast launching (dev only)
1150 CAHManager::getInstance()->runActionHandler("launch_game", NULL, toString("slot=%d|edit_mode=0", charSelect));
1152 if (LoginCharsel == -1)
1153 ClientCfg.SelectCharacter = charSelect;
1158 // Clear sending buffer that may contain prevous QUIT_GAME when getting back to the char selection screen
1159 NetMngr.flushSendBuffer();
1162 if (CharNameValidArrived)
1164 //nlinfo("impulseCallBack : received CharNameValidArrived");
1165 CharNameValidArrived = false;
1166 WaitServerAnswer = false;
1167 if (ClientCfg.SelectCharacter == -1)
1169 CCDBNodeLeaf *pNL;
1170 pNL = NLGUI::CDBManager::getInstance()->getDbProp(CharNameValidDBLink,false);
1171 if (pNL != NULL)
1173 if (CharNameValid)
1174 pNL->setValue64(1);
1175 else
1176 pNL->setValue64(0);
1179 pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:SERVER_RECEIVED_VALID", false);
1180 if (pNL != NULL)
1182 pNL->setValue64 (1); // Send impulse to interface observers
1183 IngameDbMngr.flushObserverCalls();
1184 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1185 pNL->setValue64 (0);
1186 IngameDbMngr.flushObserverCalls();
1187 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1192 if (serverReceivedReady)
1194 //nlinfo("impulseCallBack : received serverReceivedReady");
1195 serverReceivedReady = false;
1196 WaitServerAnswer = false;
1197 PlayerWantToGoInGame = true;
1200 else
1202 noUserChar = false;
1203 userChar = false;
1204 CharNameValidArrived = false;
1205 serverReceivedReady = false;
1208 // Check if server disconnect the client
1209 if (!ClientCfg.Local)
1211 if (NetMngr.getConnectionState() == CNetManager::Disconnect)
1213 // Display the connection failure screen
1214 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:CURRENT_SCREEN", false);
1215 if (pNL != NULL)
1216 pNL->setValue64 (nScreenServerCrashed);
1218 if ( firewallTimeout )
1220 // Display the firewall error string instead of the normal failure string
1221 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:outgame:crashing:title"));
1222 if (pVT != NULL)
1224 pVT->setMultiLine( true );
1225 pVT->setTextLocalized(CI18N::get("uiFirewallFail")+".\n"+
1226 CI18N::get("uiFirewallAlert")+".", false);
1234 // We want to quit the game without playing
1235 if (game_exit)
1236 return QUIT_THE_GAME;
1239 if (ClientCfg.SelectCharacter != -1)
1240 PlayerSelectedSlot = ClientCfg.SelectCharacter;
1242 // Notify the state machine that we're exiting from global menu
1243 LoginSM.pushEvent(CLoginStateMachine::ev_global_menu_exited);
1245 // Init the current Player Name (for interface.cfg and sentence.name save). Make a good File Name.
1246 string playerName = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1247 PlayerSelectedFileName = buildPlayerNameForSaveFile(playerName);
1249 // Init the current Player Home shard Id and name
1250 CharacterHomeSessionId = CharacterSummaries[PlayerSelectedSlot].Mainland;
1251 PlayerSelectedMainland= CharacterSummaries[PlayerSelectedSlot].Mainland;
1252 PlayerSelectedHomeShardName.clear();
1253 PlayerSelectedHomeShardNameWithParenthesis.clear();
1254 for(uint i=0;i<CShardNames::getInstance().getSessionNames().size();i++)
1256 const CShardNames::TSessionName &sessionName= CShardNames::getInstance().getSessionNames()[i];
1257 if(PlayerSelectedMainland == sessionName.SessionId)
1259 PlayerSelectedHomeShardName= sessionName.DisplayName;
1260 PlayerSelectedHomeShardNameWithParenthesis= '(' + PlayerSelectedHomeShardName + ')';
1265 // Restore video mode
1266 if (ClientCfg.SelectCharacter == -1)
1267 connectionRestoreVideoMode ();
1269 // Skip intro next time
1270 ClientCfg.writeBool("SkipIntro", true);
1272 // return SELECT_CHARACTER;
1273 return GOGOGO_IN_THE_GAME;
1277 // Init the character selection slot texts from the character summaries
1278 // ------------------------------------------------------------------------------------------------
1279 class CAHNetInitCharSel : public IActionHandler
1281 public:
1282 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1284 string sPath = getParam(Params, "slottexts");
1285 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1286 uint i;
1287 for (i = 0; i < CharacterSummaries.size(); ++i)
1289 CCharacterSummary &rCS = CharacterSummaries[i];
1290 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i));
1291 CViewText *pVT = dynamic_cast<CViewText*>(pIE);
1292 if (pVT == NULL) return;
1294 if (rCS.Name.empty())
1295 pVT->setTextLocalized("uiEmptySlot", true);
1296 else
1297 pVT->setTextLocalized(rCS.Name.toUtf8(), false);
1299 // 5 slots
1300 for (; i < 5; ++i)
1302 CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId(sPath+":text"+NLMISC::toString(i)));
1303 if (pVT == NULL) return;
1304 pVT->setTextLocalized("uiEmptySlot", true);
1308 REGISTER_ACTION_HANDLER (CAHNetInitCharSel, "net_init_char_sel");
1310 // ------------------------------------------------------------------------------------------------
1311 void setTarget(CCtrlBase *ctrl, const string &targetName, std::string &value)
1313 std::vector<CInterfaceLink::CTargetInfo> targets;
1314 // find first enclosing group
1315 CCtrlBase *currCtrl = ctrl;
1316 CInterfaceGroup *ig = NULL;
1317 while (currCtrl)
1319 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1320 if (ig != NULL) break;
1321 currCtrl = currCtrl->getParent();
1323 if (ig)
1325 CInterfaceExprValue exprValue;
1326 exprValue.setString(value);
1328 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1329 for(uint k = 0; k < targets.size(); ++k)
1331 if (targets[k].Elem) targets[k].affect(exprValue);
1336 // ------------------------------------------------------------------------------------------------
1337 void setTarget(CCtrlBase *ctrl, const string &targetName, uint32 value)
1339 std::vector<CInterfaceLink::CTargetInfo> targets;
1340 // find first enclosing group
1341 CCtrlBase *currCtrl = ctrl;
1342 CInterfaceGroup *ig = NULL;
1343 while (currCtrl)
1345 ig = dynamic_cast<CInterfaceGroup *>(currCtrl);
1346 if (ig != NULL) break;
1347 currCtrl = currCtrl->getParent();
1349 if (ig)
1351 CInterfaceExprValue exprValue;
1352 exprValue.setInteger(value);
1354 CInterfaceLink::splitLinkTargets(targetName, ig, targets);
1355 for(uint k = 0; k < targets.size(); ++k)
1357 if (targets[k].Elem) targets[k].affect(exprValue);
1362 // ------------------------------------------------------------------------------------------------
1363 class CAHGetSlot: public IActionHandler
1365 public:
1366 virtual void execute (CCtrlBase *pCaller, const string &Params)
1368 string sProp = getParam(Params, "prop");
1369 string sTarget = getParam(Params, "target");
1370 string sSlot = getParam(Params, "slot");
1372 CInterfaceExprValue result;
1373 if (!CInterfaceExpr::eval(sSlot, result))
1374 return;
1375 uint8 selectedSlot = (uint8)result.getInteger();
1376 if (selectedSlot >= CharacterSummaries.size())
1377 return;
1379 PlayerSelectedSlot = selectedSlot;
1381 if (CharacterSummaries[PlayerSelectedSlot].Name.empty())
1382 return;
1384 string sValue;
1385 uint32 nValue = 0;
1387 if (sProp == "name")
1389 sValue = CharacterSummaries[PlayerSelectedSlot].Name.toUtf8();
1390 setTarget (pCaller, sTarget, sValue);
1392 /* else if (sProp == "surname")
1393 Deprecated {
1394 sValue = CharacterSummaries[PlayerSelectedSlot].Surname;
1395 setTarget (pCaller, sTarget, sValue);
1397 */ else if (sProp == "title")
1399 bool womanTitle;
1400 if( CharacterSummaries[PlayerSelectedSlot].VisualPropA.PropertySubData.Sex == 1 )
1402 UserEntity->setGender( GSGENDER::female );
1403 womanTitle = true;
1405 else
1407 UserEntity->setGender( GSGENDER::male );
1408 womanTitle = false;
1410 string titleStr = CHARACTER_TITLE::toString(CharacterSummaries[PlayerSelectedSlot].Title);
1411 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(titleStr, womanTitle);
1413 // Sometimes translation contains another title
1414 string::size_type pos = sValue.find('$');
1415 if (pos != string::npos)
1417 sValue = STRING_MANAGER::CStringManagerClient::getTitleLocalizedName(CEntityCL::getTitleFromName(sValue), womanTitle);
1420 setTarget (pCaller, sTarget, sValue);
1422 /* else if (sProp == "orient")
1423 Deprecated {
1424 sValue = ROLES::roleToUCString(CharacterSummaries[PlayerSelectedSlot].Role);
1425 setTarget (pCaller, sTarget, sValue);
1427 else if (sProp == "job")
1429 //Deprecated
1430 // sValue = JOBS::jobToUCString(CharacterSummaries[PlayerSelectedSlot].Job);
1431 sValue = JOBS::jobToUCString(JOBS::BladeBearer);
1432 setTarget (pCaller, sTarget, sValue);
1434 */ else if (sProp == "level")
1436 //Deprecated
1437 // sValue = toString(CharacterSummaries[PlayerSelectedSlot].JobLevel);
1438 sValue = toString(1);
1439 setTarget (pCaller, sTarget, sValue);
1441 else if (sProp == "pos")
1443 nValue = CharacterSummaries[PlayerSelectedSlot].Location;
1444 setTarget (pCaller, sTarget, nValue);
1448 REGISTER_ACTION_HANDLER (CAHGetSlot, "get_slot");
1451 // Setup the database from a database entry which represents a slot
1452 // ------------------------------------------------------------------------------------------------
1453 class CAHSetDBFromSlot : public IActionHandler
1455 public:
1456 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1458 string sDBLink = getParam(Params, "dblink");
1459 string sSlot = getParam(Params, "slot");
1461 CInterfaceExprValue result;
1462 if (!CInterfaceExpr::eval(sSlot, result))
1463 return;
1465 PlayerSelectedSlot = (uint8)result.getInteger();
1467 if (PlayerSelectedSlot >= CharacterSummaries.size())
1468 return;
1470 // Setup the database from the character summary
1471 CCharacterSummary &rCS = CharacterSummaries[PlayerSelectedSlot];
1472 if (rCS.Name.empty())
1473 return;
1475 SCharacter3DSetup::setupDBFromCharacterSummary(sDBLink, rCS);
1478 REGISTER_ACTION_HANDLER (CAHSetDBFromSlot, "set_db_from_slot");
1481 // Reset all the pushed radio button of a group
1482 // ------------------------------------------------------------------------------------------------
1483 class CAHResetPushed: public IActionHandler
1485 public:
1486 virtual void execute (CCtrlBase *pCaller, const string &Params)
1488 string sDBLink = getParam(Params, "dblink");
1489 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1490 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(pCaller->getId(), sDBLink);
1491 CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup*>(pIE);
1492 if (pIG == NULL) return;
1494 const vector<CCtrlBase*> vCB = pIG->getControls();
1495 for (uint i = 0; i < vCB.size(); ++i)
1497 CCtrlBaseButton *pBut = dynamic_cast<CCtrlBaseButton*>(vCB[i]);
1498 if (pBut && pBut->getType() == CCtrlBaseButton::RadioButton)
1500 pBut->setPushed (false);
1505 REGISTER_ACTION_HANDLER (CAHResetPushed, "reset_pushed");
1511 // Launch the game given a slot (slot is reference to the character summaries
1512 // ------------------------------------------------------------------------------------------------
1513 class CAHLaunchGame : public IActionHandler
1515 public:
1516 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1518 // Get the edit/play mode
1519 string sEditMode = getParam(Params, "edit_mode");
1520 bool wantsEditMode = false;
1521 CInterfaceExprValue result;
1522 bool wantsNewScenario = false;
1524 if (CInterfaceExpr::eval(sEditMode, result))
1526 wantsEditMode = (result.getInteger() == 1) || (result.getInteger() == 2);
1527 wantsNewScenario = (result.getInteger() == 2);
1530 CInterfaceManager *im = CInterfaceManager::getInstance();
1531 if (wantsEditMode)
1533 // full patch needed for edition, warn the client
1534 if (AvailablePatchs != 0)
1536 if (im->isInGame())
1538 inGamePatchUncompleteWarning();
1540 else
1542 im->messageBoxWithHelp(CI18N::get("uiBGD_FullPatchNeeded"), "ui:outgame");
1544 return;
1548 // Get the player selected slot
1549 string sSlot = getParam(Params, "slot");
1550 if (sSlot != "ingame_auto")
1552 CInterfaceExprValue result;
1553 if (!CInterfaceExpr::eval(sSlot, result))
1554 return;
1555 PlayerSelectedSlot = (uint8)result.getInteger();
1556 if (PlayerSelectedSlot >= CharacterSummaries.size())
1557 return;
1559 ClientCfg.writeInt("SelectedSlot",PlayerSelectedSlot);
1560 if (ClientCfg.SaveConfig)
1561 ClientCfg.ConfigFile.save();
1566 static volatile bool isMainlandCharacter = false; // TMP until we can get this info
1567 if (isMainlandCharacter)
1569 nlassert(0); // use id="message_box" !!!
1570 if (AvailablePatchs != 0)
1572 im->messageBoxWithHelp(CI18N::get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame");
1574 return;
1579 // Select the right sheet to create the user character.
1580 ClientCfg.UserSheet = CharacterSummaries[PlayerSelectedSlot].SheetId.toString();
1582 // If the user wants to enter its editing session, get the ring server to Far TP to.
1583 if (wantsEditMode)
1586 if (wantsNewScenario)
1588 CSessionBrowserImpl &sb = CSessionBrowserImpl::getInstance();
1589 sb.init(NULL);
1590 sb.closeEditSession(sb.getCharId());
1591 sb.waitOneMessage(CSessionBrowserImpl::getMessageName("on_invokeResult"));
1593 if (FarTP.requestFarTPToSession( (TSessionId)0, PlayerSelectedSlot, CFarTP::LaunchEditor, false ))
1595 WaitServerAnswer = true; // prepare to receive the character messages
1598 // // If the player clicked 'Launch Editor', there was no CONNECTION:SELECT_CHAR sent yet,
1599 // // so don't wait for the EGS to acknowledge our quit message as he does not know our character
1600 // LoginSM.pushEvent(CLoginStateMachine::ev_ingame_return);
1602 return;
1605 // Send CONNECTION:SELECT_CHAR
1606 CBitMemStream out;
1607 nlverify( GenericMsgHeaderMngr.pushNameToStream ("CONNECTION:SELECT_CHAR", out) );
1608 //nlinfo("impulseCallBack : CONNECTION:SELECT_CHAR '%d' sent.", PlayerSelectedSlot);
1611 CSelectCharMsg SelectCharMsg;
1612 SelectCharMsg.c = (uint8)PlayerSelectedSlot;
1613 out.serial (SelectCharMsg);
1614 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1616 NetMngr.push(out);
1617 NetMngr.send(NetMngr.getCurrentServerTick());
1620 //PlayerWantToGoInGame = true;
1622 // CBitMemStream out2;
1623 // if(GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ENTER", out2))
1624 // {
1625 // NetMngr.push(out2);
1626 // nlinfo("impulseCallBack : CONNECTION:ENTER sent");
1627 // }
1628 // else
1629 // nlwarning("unknown message name : 'CONNECTION:ENTER'.");
1631 WaitServerAnswer = true;
1632 if (ClientCfg.Local)
1633 serverReceivedReady = true;
1636 REGISTER_ACTION_HANDLER (CAHLaunchGame, "launch_game");
1639 // Ask the server to create a character
1640 // ------------------------------------------------------------------------------------------------
1641 class CAHAskCreateChar : public IActionHandler
1643 public:
1644 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1646 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1648 // Create the message for the server to create the character.
1649 CBitMemStream out;
1650 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out))
1652 nlwarning ("don't know message name CONNECTION:CREATE_CHAR");
1653 return;
1656 // Setup the name
1657 string sEditBoxPath = getParam (Params, "name");
1658 string sFirstName = "NotSet";
1659 string sSurName = "NotSet";
1660 CGroupEditBox *pGEB = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(sEditBoxPath));
1661 if (pGEB != NULL)
1662 sFirstName = pGEB->getInputString();
1663 else
1664 nlwarning ("can't get edit box name : %s",sEditBoxPath.c_str());
1666 // Build the character summary from the database branch ui:temp:char3d
1667 CCharacterSummary CS;
1668 string sCharSumPath = getParam(Params, "charsum");
1669 SCharacter3DSetup::setupCharacterSummaryFromDB(CS, sCharSumPath);
1670 CS.Mainland = MainlandSelected;
1671 CS.Name = ucstring::makeFromUtf8(sFirstName); // FIXME: UTF-8 (serial)
1672 //CS.Surname = sSurName;
1674 // Create the message to send to the server from the character summary
1675 CCreateCharMsg CreateCharMsg;
1677 CreateCharMsg.setupFromCharacterSummary(CS);
1679 // Slot
1681 string sSlot = getParam(Params, "slot");
1683 CInterfaceExprValue result;
1684 if (!CInterfaceExpr::eval(sSlot, result))
1685 return;
1687 CreateCharMsg.Slot = (uint8)result.getInteger();
1689 NLGUI::CDBManager::getInstance()->getDbProp("UI:SELECTED_SLOT")->setValue32(PlayerSelectedSlot);
1692 // Setup the new career
1693 string sCaracBasePath = getParam (Params, "caracs");
1694 CreateCharMsg.NbPointFighter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FIGHT")->getValue32();
1695 CreateCharMsg.NbPointCaster = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"MAGIC")->getValue32();
1696 CreateCharMsg.NbPointCrafter = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"CRAFT")->getValue32();
1697 CreateCharMsg.NbPointHarvester = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sCaracBasePath+"FORAGE")->getValue32();
1699 // Setup starting point
1700 string sLocationPath = getParam(Params, "loc");
1702 CreateCharMsg.StartPoint = RYZOM_STARTING_POINT::borea;
1704 CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp (sLocationPath, false);
1705 if (pNL != NULL)
1706 CreateCharMsg.StartPoint = (RYZOM_STARTING_POINT::TStartPoint)(pNL->getValue64());
1707 else
1708 nlwarning(("Can't read starting point from the database : " + sLocationPath).c_str());
1710 if (CS.People == EGSPD::CPeople::Fyros)
1711 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::fyros_start));
1712 else if (CS.People == EGSPD::CPeople::Matis)
1713 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::matis_start));
1714 else if (CS.People == EGSPD::CPeople::Tryker)
1715 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::tryker_start));
1716 else // if (CS.People == EGSPD::CPeople::Zorai)
1717 CreateCharMsg.StartPoint= (RYZOM_STARTING_POINT::TStartPoint)(((uint8)CreateCharMsg.StartPoint) + ((uint8)RYZOM_STARTING_POINT::zorai_start));
1721 // Send the message to the server
1722 CreateCharMsg.serialBitMemStream (out);
1723 if (!ClientCfg.Local/*!ClientCfg.Light*/)
1725 noUserChar = userChar = false;
1727 NetMngr.push(out);
1728 NetMngr.send(NetMngr.getCurrentServerTick());
1730 //nlinfo("impulseCallBack : CONNECTION:CREATE_CHAR sent");
1731 CreateCharMsg.dump();
1733 else
1735 userChar = true;
1736 if (CharacterSummaries.size() < 5)
1737 CharacterSummaries.push_back(CS);
1739 WaitServerAnswer = true;
1742 REGISTER_ACTION_HANDLER (CAHAskCreateChar, "ask_create_char");
1746 // Ask the server to delete a character
1747 // ------------------------------------------------------------------------------------------------
1748 class CAHAskDeleteChar : public IActionHandler
1750 public:
1751 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1753 // Create the message for the server to create the character.
1754 CBitMemStream out;
1755 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:DELETE_CHAR", out))
1757 nlwarning ("don't know message name CONNECTION:DELETE_CHAR");
1758 return;
1761 // Get the selected slot
1762 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1764 string sSlot = getParam(Params, "slot");
1766 CInterfaceExprValue result;
1767 if (!CInterfaceExpr::eval(sSlot, result))
1768 return;
1770 uint8 nSelectedSlot = (uint8)result.getInteger();
1771 if (nSelectedSlot >= CharacterSummaries.size())
1772 return;
1774 out.serial (nSelectedSlot);
1776 // Yoyo: delete the Local files. To avoid problem if recreate a character with same name.
1777 string playerName = CharacterSummaries[nSelectedSlot].Name.toUtf8();
1778 string playerDeletedFileName = buildPlayerNameForSaveFile(playerName);
1779 // Delete the 2 Local files
1780 pIM->deletePlayerConfig(playerDeletedFileName);
1781 pIM->deletePlayerKeys(playerDeletedFileName);
1783 // Send the message to the server
1784 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1786 noUserChar = userChar = false;
1787 NetMngr.push(out);
1788 NetMngr.send(NetMngr.getCurrentServerTick());
1790 //nlinfo("impulseCallBack : CONNECTION:DELETE_CHAR %d sent", nSelectedSlot);
1792 else
1794 if (nSelectedSlot < CharacterSummaries.size())
1795 CharacterSummaries.erase (CharacterSummaries.begin()+nSelectedSlot);
1796 if (CharacterSummaries.size() != 0)
1797 userChar = true;
1798 else
1799 noUserChar = true;
1801 WaitServerAnswer = true;
1804 REGISTER_ACTION_HANDLER (CAHAskDeleteChar, "ask_delete_char");
1806 // ------------------------------------------------------------------------------------------------
1807 string getTarget(CCtrlBase * /* ctrl */, const string &targetName)
1809 string sTmp = targetName;
1810 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1811 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1813 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1815 CInterfaceElement *elem = rTI.Elem;
1816 if (!elem)
1818 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1819 return "";
1821 const CReflectedProperty *pRP = CReflectSystem ::getProperty(elem->getReflectedClassName(), rTI.PropertyName);
1823 if (pRP->Type == CReflectedProperty::String)
1824 return ((elem->*(pRP->GetMethod.GetString))());
1825 return "";
1828 #ifdef RYZOM_LUA_UCSTRING
1829 // ------------------------------------------------------------------------------------------------
1830 ucstring getUCTarget(CCtrlBase * /* ctrl */, const string &targetName)
1832 string sTmp = targetName;
1833 std::vector<CInterfaceLink::CTargetInfo> targetsVector;
1834 CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
1836 CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
1838 CInterfaceElement *elem = rTI.Elem;
1839 if (!elem)
1841 nlwarning("<CInterfaceExpr::getprop> : Element is NULL");
1842 return ucstring(""); // TODO: UTF-8 Lua
1844 const CReflectedProperty *pRP = elem->getReflectedProperty(rTI.PropertyName);
1846 if (pRP->Type == CReflectedProperty::UCString)
1847 return ((elem->*(pRP->GetMethod.GetUCString))());
1848 return ucstring(""); // TODO: UTF-8 Lua
1850 #endif
1852 /*// Ask the server to rename a character
1853 // ------------------------------------------------------------------------------------------------
1854 class CAHAskRenameChar : public IActionHandler
1856 public:
1857 virtual void execute (CCtrlBase *pCaller, const string &Params)
1859 string sName = getTarget(NULL,getParam(Params, "name"));
1860 string sSurname = getTarget(NULL,getParam(Params, "surname"));
1862 string sDBSlot = getParam(Params, "dbslot");
1864 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1865 uint8 nSelectedSlot = (uint8)NLGUI::CDBManager::getInstance()->getDbProp(sDBSlot,false)->getValue32();
1867 if (nSelectedSlot > CharacterSummaries.size())
1868 return;
1870 // Create the message for the server to create the character.
1871 CBitMemStream out;
1872 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:RENAME_CHAR", out))
1874 nlwarning ("don't know message name CONNECTION:RENAME_CHAR");
1875 return;
1878 // Get the selected slot
1879 out.serial (nSelectedSlot);
1880 out.serial (sName);
1881 out.serial (sSurname);
1883 // Send the message to the server
1884 if (!ClientCfg.Light)
1886 noUserChar = userChar = false;
1887 NetMngr.push (out);
1888 NetMngr.send (NetMngr.getCurrentServerTick());
1890 nldebug("impulseCallBack : CONNECTION:RENAME_CHAR sent");
1892 // Wait for the character message which describe all the characters on a server
1893 while (!noUserChar && !userChar)
1895 //NetMngr.waitForServer();
1896 NetMngr.update();
1897 NetMngr.send();
1898 nlSleep(100);
1901 else
1903 CharacterSummaries[nSelectedSlot].FirstName = sName;
1904 CharacterSummaries[nSelectedSlot].Surname = sSurname;
1908 REGISTER_ACTION_HANDLER (CAHAskRenameChar, "ask_rename_char");
1911 // Ask the server if the name is not already used
1912 // ------------------------------------------------------------------------------------------------
1913 class CAHAskValidName : public IActionHandler
1915 public:
1916 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1918 string sTarget = getParam(Params, "target");
1919 string sDBLink = getParam(Params, "dblink");
1920 CharNameValidDBLink = sDBLink;
1922 #ifdef RYZOM_LUA_UCSTRING
1923 string sName = getUCTarget(NULL,sTarget).toUtf8(); // TODO: UTF-8 Lua
1924 #else
1925 string sName = getTarget(NULL, sTarget);
1926 #endif
1928 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1929 if (sName.empty())
1931 NLGUI::CDBManager::getInstance()->getDbProp(sDBLink,false)->setValue32(0);
1932 return;
1935 // Ask the server
1936 CharNameValid = true;
1938 // PATCH DU BUG DE L'ESPACE !!!
1939 if (sName.find(' ') != ucstring::npos)
1940 CharNameValid = false;
1941 // PATCH DU BUG DE L'ESPACE !!!
1944 if (CharNameValid)
1946 if (!ClientCfg.Local/*ace!ClientCfg.Light*/)
1949 CBitMemStream out;
1950 if (!GenericMsgHeaderMngr.pushNameToStream("CONNECTION:ASK_NAME", out))
1952 nlwarning ("don't know message name CONNECTION:ASK_NAME");
1953 return;
1956 CCheckNameMsg checkNameMsg;
1957 checkNameMsg.Name = sName;
1958 checkNameMsg.HomeSessionId = MainlandSelected;
1959 checkNameMsg.serialBitMemStream(out);
1961 NewKeysCharNameWanted = sName;
1962 // append shard name
1963 for(uint k = 0; k < Mainlands.size(); ++k)
1965 if (Mainlands[k].Id == MainlandSelected)
1967 // extract name from mainland
1968 /*ucstring::size_type first = Mainlands[k].Name.find('('); // OLD
1969 ucstring::size_type last = Mainlands[k].Name.find(')');// OLD
1970 if (first != ucstring::npos && last != ucstring::npos && first < last)// OLD
1972 NewKeysCharNameWanted += Mainlands[k].Name.substr(first, last - first + 1);
1974 NewKeysCharNameWanted += ('(' + Mainlands[k].Name.toUtf8() + ')');
1975 break;
1979 NewKeysCharNameValidated.clear();
1981 NetMngr.push(out);
1982 NetMngr.send(NetMngr.getCurrentServerTick());
1984 //nlinfo("impulseCallBack : CONNECTION:ASK_NAME sent");
1986 // Wait for the valid character name message
1987 CharNameValidArrived = false;
1989 else
1992 CharNameValid = true;
1993 CharNameValidArrived = true;
1995 for (uint i = 0; i < CharacterSummaries.size(); ++i)
1997 string ls = CharacterSummaries[i].Name.toString();
1998 if (ls == sName)
1999 CharNameValid = false;
2003 else
2005 CharNameValidArrived = true;
2007 WaitServerAnswer = true;
2010 REGISTER_ACTION_HANDLER (CAHAskValidName, "ask_valid_name");
2012 // ------------------------------------------------------------------------------------------------
2013 class CAHPlaySound : public IActionHandler
2015 public:
2016 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2018 string sName = getParam(Params, "name");
2019 TStringId id = CStringMapper::map(sName);
2020 if (SoundMngr != NULL)
2021 SoundMngr->spawnSource(id,CVector(0,0,0));
2024 REGISTER_ACTION_HANDLER (CAHPlaySound, "play_sound");
2026 // ------------------------------------------------------------------------------------------------
2027 class CAHPlayMusicOutgame : public IActionHandler
2029 public:
2030 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2032 // get the name of the wanted music
2033 string sName = getParam(Params, "name");
2034 bool async;
2035 fromString(getParam(Params, "async"), async);
2037 // if empty name, return to default mode
2038 if (sName.empty())
2039 sName = ClientCfg.EmptySlotMusic;
2041 // change the music
2042 SoundGlobalMenu.setMusic(sName, async);
2045 REGISTER_ACTION_HANDLER (CAHPlayMusicOutgame, "play_music_outgame");
2047 // ------------------------------------------------------------------------------------------------
2048 class CAHRepeatUntil : public IActionHandler
2050 public:
2051 virtual void execute (CCtrlBase *pCaller, const string &Params)
2053 string sProc = getParam(Params, "proc");
2054 string sCond = getParam(Params, "cond");
2055 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2057 for(;;)
2059 vector<string> p;
2060 p.push_back(sProc);
2061 CWidgetManager::getInstance()->runProcedure(sProc, pCaller, p);
2063 CInterfaceExprValue result;
2064 if (CInterfaceExpr::eval(sCond, result))
2066 if (result.getBool())
2067 break;
2069 else
2071 break;
2077 REGISTER_ACTION_HANDLER (CAHRepeatUntil, "repeatuntil");
2080 // ------------------------------------------------------------------------------------------------
2081 class CAHDispInfo : public IActionHandler
2083 public:
2084 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2086 string sStr = getParam(Params, "str");
2087 string sVal = getParam(Params, "val");
2089 string res;
2091 CInterfaceExprValue result;
2092 if (CInterfaceExpr::eval(sStr, result))
2094 if (result.toString())
2096 res += result.getString();
2099 if (CInterfaceExpr::eval(sVal, result))
2101 if (result.toString())
2103 res += result.getString();
2107 nlinfo(res.c_str());
2110 REGISTER_ACTION_HANDLER (CAHDispInfo, "disp_info");
2113 // ***************************************************************************
2114 class CAHInitMainlandList : public IActionHandler
2116 public:
2118 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2120 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2122 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2123 if (pList == NULL)
2125 nlwarning("element " GROUP_LIST_MAINLAND " not found probably bad outgame.xml");
2126 return;
2129 CInterfaceGroup *pPrevLine = NULL;
2130 for(uint i = 0; i < Mainlands.size(); i++)
2132 vector< pair < string, string > > params;
2133 params.clear();
2134 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2135 if (i>0)
2136 params.push_back(pair<string,string>("posref", "BL TL"));
2138 CInterfaceGroup *pNewLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_mainland", GROUP_LIST_MAINLAND, params);
2139 if (pNewLine != NULL)
2141 CViewBase *pVBon = pNewLine->getView("online");
2142 CViewBase *pVBoff = pNewLine->getView("offline");
2143 if ((pVBon != NULL) && (pVBoff != NULL))
2145 pVBon->setActive(Mainlands[i].Online);
2146 pVBoff->setActive(!Mainlands[i].Online);
2149 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2150 if (pVT != NULL)
2152 std::string str = Mainlands[i].Name.toUtf8() + " " + Mainlands[i].Description.toUtf8();
2153 pVT->setTextLocalized(str, false);
2156 // Add to the list
2157 pNewLine->setParent(pList);
2158 pNewLine->setParentSize(pList);
2159 pNewLine->setParentPos(pPrevLine);
2160 pList->addGroup(pNewLine);
2162 pPrevLine = pNewLine;
2165 // UI Patch
2166 if (!Mainlands.empty())
2168 //choose default mainland from language code
2169 uint32 defaultMainland = 0;
2170 for(uint i = 0; i < Mainlands.size(); i++)
2172 if( Mainlands[i].LanguageCode == ClientCfg.LanguageCode )
2174 defaultMainland = i;
2175 break;
2179 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND ":"+toString(Mainlands[defaultMainland].Id)+":but"));
2180 if (pCB != NULL)
2182 pCB->setPushed(true);
2183 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2186 pList->invalidateCoords();
2189 REGISTER_ACTION_HANDLER (CAHInitMainlandList, "init_mainland_list");
2192 // ***************************************************************************
2193 class CAHResetMainlandList : public IActionHandler
2195 public:
2197 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2199 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2200 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2201 pList->clearGroups();
2204 REGISTER_ACTION_HANDLER (CAHResetMainlandList, "reset_mainland_list");
2207 // ***************************************************************************
2208 class CAHMainlandSelect : public IActionHandler
2210 virtual void execute (CCtrlBase *pCaller, const std::string &Params)
2212 //nlinfo("CAHMainlandSelect called");
2213 struct CUnpush : public CInterfaceElementVisitor
2215 CCtrlBase *Ref;
2216 virtual void visitCtrl(CCtrlBase *ctrl)
2218 if (ctrl == Ref) return;
2219 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(ctrl);
2220 if (but)
2222 but->setPushed(false);
2226 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_MAINLAND));
2227 if (!list)
2228 return;
2230 // unselect
2231 if (Params.empty())
2233 CUnpush unpusher;
2234 unpusher.Ref = pCaller;
2235 list->visit(&unpusher);
2238 // now select
2239 uint32 mainland;
2240 if (Params.empty())
2242 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pCaller);
2243 if (!pCB)
2244 return;
2246 std::string name = pCB->getId();
2247 name = name.substr(0, name.rfind(':'));
2249 if (!fromString(name.substr(name.rfind(':')+1, name.size()), mainland))
2250 return;
2252 pCB->setPushed(true);
2254 else
2255 if (!fromString(Params, mainland))
2256 return;
2258 // and store
2259 MainlandSelected = (TSessionId)mainland;
2262 REGISTER_ACTION_HANDLER (CAHMainlandSelect, "mainland_select");
2265 // ***************************************************************************
2266 class CAHInitKeysetList : public IActionHandler
2268 public:
2272 CInterfaceGroup *PrevLine;
2273 CInterfaceGroup *List;
2274 bool First;
2276 CInterfaceGroup *buildTemplate(const std::string &templateName, const std::string &id)
2278 vector< pair < string, string > > params;
2279 params.clear();
2280 params.push_back(pair<string,string>("id", id));
2281 if (!First)
2283 params.push_back(pair<string,string>("posref", "BL TL"));
2285 First = false;
2286 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2287 return CWidgetManager::getInstance()->getParser()->createGroupInstance(templateName, GROUP_LIST_KEYSET, params);
2290 void addGroupInList(CInterfaceGroup *pNewLine)
2292 if (!pNewLine) return;
2293 // Add to the list
2294 pNewLine->setParent(List);
2295 pNewLine->setParentSize(List);
2296 pNewLine->setParentPos(PrevLine);
2297 List->addGroup(pNewLine);
2299 PrevLine = pNewLine;
2302 void addSeparator()
2304 addGroupInList(buildTemplate("t_keyseparator", ""));
2307 // add a new keyset in the list
2308 void addKeySet(const std::string &filename, const std::string &name, const std::string tooltip)
2310 nlassert(List);
2311 CInterfaceGroup *pNewLine = buildTemplate("t_keyset", toString(filename));
2312 if (pNewLine != NULL)
2314 CViewText *pVT = dynamic_cast<CViewText*>(pNewLine->getView("name"));
2315 if (pVT != NULL)
2317 pVT->setTextLocalized(name, false);
2320 CCtrlBase *pBut = pNewLine->getCtrl("but");
2321 if (pBut != NULL)
2323 pBut->setDefaultContextHelp(tooltip);
2325 addGroupInList(pNewLine);
2329 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2331 NewKeysCharNameWanted.clear();
2332 NewKeysCharNameValidated.clear();
2333 GameKeySet = "keys.xml";
2334 RingEditorKeySet = "keys_r2ed.xml";
2335 First = true;
2336 PrevLine = NULL;
2337 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2339 List = dynamic_cast<CInterfaceGroup *>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2340 if (List == NULL)
2342 nlwarning("element " GROUP_LIST_KEYSET " not found probably bad outgame.xml");
2343 return;
2346 // built-in keysets
2347 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2348 sint wasdIndex = -1;
2349 sint zqsdIndex = -1;
2350 if (keySetVar && keySetVar->size() != 0)
2352 for (uint k = 0; k < keySetVar->size(); ++k)
2354 if (keySetVar->asString(k) == "zqsd") zqsdIndex = (sint) k;
2355 if (keySetVar->asString(k) == "wasd") wasdIndex = (sint) k;
2357 std::string strId = "uiCP_KeysetName_" + keySetVar->asString(k);
2358 strFindReplace(strId, ".", "_");
2359 const string &keySetName = CI18N::get(strId);
2360 strId = "uiCP_KeysetTooltip_" + keySetVar->asString(k);
2361 strFindReplace(strId, ".", "_");
2362 if (CI18N::hasTranslation(strId))
2364 const string &keySetTooltip = CI18N::get(strId);
2365 addKeySet(keySetVar->asString(k), keySetName, keySetTooltip);
2369 else
2371 nlwarning("'%s' var not found in config file, or list is empty, proposing default keyset only", KeySetVarName);
2372 std::string defaultKeySet = "keys";
2373 const string &keySetName = CI18N::get("uiCP_KeysetName_" + defaultKeySet);
2374 const string &keySetTooltip = CI18N::get("uiCP_KeysetTooltip_" + defaultKeySet);
2375 addKeySet(defaultKeySet, keySetName, keySetTooltip);
2378 // keyset from previous chars
2379 std::vector<std::string> savedFiles;
2380 CPath::getPathContent("save/", false, false, true, savedFiles);
2381 enum { GameKeys = 0x1, EditorKeys = 0x2 };
2382 typedef std::map<std::string, uint> TKeySetFileMap;
2383 TKeySetFileMap keySetFiles; // combination of 'GameKeys' & 'EditorKeys' flag for each character
2384 for (uint k = 0; k < savedFiles.size(); ++k)
2386 if (testWildCard(CFile::getFilename(savedFiles[k]), "keys_*.xml"))
2388 bool editorKeys = testWildCard(CFile::getFilename(savedFiles[k]), "keys_r2ed_*.xml");
2389 std::string baseName = CFile::getFilenameWithoutExtension(savedFiles[k]).substr(strlen(editorKeys ? "keys_r2ed_" : "keys_"));
2390 if(!keySetFiles.count(baseName)) keySetFiles[baseName] = 0;
2391 keySetFiles[baseName] |= editorKeys ? EditorKeys : GameKeys;
2395 bool separatorAdded = false;
2396 if (!keySetFiles.empty())
2398 for(TKeySetFileMap::iterator it = keySetFiles.begin(); it != keySetFiles.end(); ++it)
2400 string name;
2401 if (ClientCfg.Local)
2403 name = it->first;
2405 else
2407 // search matching utf-8 string name from character summaries
2408 for (uint k = 0; k < CharacterSummaries.size(); ++k)
2410 if (it->first == buildPlayerNameForSaveFile(CharacterSummaries[k].Name.toUtf8()))
2412 name = CharacterSummaries[k].Name.toUtf8();
2416 if (!name.empty())
2418 if (!separatorAdded)
2420 addSeparator();
2421 separatorAdded = true;
2423 addKeySet(it->first, it->first, CI18N::get(std::string("uiCP_KeysetImport") + (it->second & GameKeys ? "_Game" : "")
2424 + (it->second & EditorKeys ? "_Editor" : "")));
2429 // default to 'ZQSD' for French and Belgian keyboard, 'WASD' else
2430 bool wasd = !CSystemUtils::isAzertyKeyboard();
2432 /*sint startIndex = wasd ? wasdIndex : zqsdIndex;
2433 if (startIndex == -1) startIndex = 0;
2435 // TMP TMP : no way to have 2 keys for the same action for now -> default to 'arrows' setting.
2436 sint startIndex = 0;
2437 nlassert(startIndex >= 0);
2438 if (startIndex < (sint) List->getNumGroup())
2440 CInterfaceGroup *gr = dynamic_cast<CInterfaceGroup *>(List->getGroup(startIndex));
2441 if (gr)
2443 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(gr->getCtrl("but"));
2444 if (pCB != NULL)
2446 pCB->setPushed(true);
2447 CAHManager::getInstance()->runActionHandler (pCB->getActionOnLeftClick(), pCB, pCB->getParamsOnLeftClick());
2451 List->invalidateCoords();
2454 REGISTER_ACTION_HANDLER (CAHInitKeysetList, "init_keyset_list");
2457 // ***************************************************************************
2458 class CAHResetKeysetList : public IActionHandler
2460 public:
2462 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2464 //CInterfaceManager *pIM = CInterfaceManager::getInstance();
2465 CInterfaceGroup *pList = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2466 pList->clearGroups();
2469 REGISTER_ACTION_HANDLER (CAHResetKeysetList, "reset_keyset_list");
2472 // ***************************************************************************
2473 class CAHResetKeysetSelect : public IActionHandler
2475 std::string getIdPostFix(const std::string fullId)
2477 std::string::size_type pos = fullId.find_last_of(":");
2478 if (pos != std::string::npos)
2479 return fullId.substr(pos + 1);
2481 return "";
2484 virtual void execute(CCtrlBase *pCaller, const std::string &Params)
2486 // 'unpush' all groups but the caller
2487 struct CUnpush : public CInterfaceElementVisitor
2489 CCtrlBase *Ref;
2490 virtual void visitCtrl(CCtrlBase *ctrl)
2492 if (ctrl == Ref) return;
2493 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(ctrl);
2494 if (but)
2496 but->setPushed(false);
2500 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_KEYSET));
2501 if (!list)
2502 return;
2504 // unselect
2505 CUnpush unpusher;
2506 unpusher.Ref = pCaller;
2507 list->visit(&unpusher);
2509 // now select
2510 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(pCaller);
2511 if (but)
2512 but->setPushed(true);
2514 std::string id;
2515 if (Params.empty())
2517 if (!pCaller) return;
2518 if (!pCaller->getParent()) return;
2520 id = getIdPostFix(pCaller->getParent()->getId());
2522 else
2523 id = getIdPostFix(Params);
2525 GameKeySet = "keys.xml";
2526 RingEditorKeySet = "keys_r2ed.xml";
2528 // compute the two filenames from the id
2529 // if id is in the built-in keysets
2530 CConfigFile::CVar *keySetVar = ClientCfg.ConfigFile.getVarPtr(KeySetVarName);
2531 if (keySetVar && keySetVar->size() > 0)
2533 for (uint k = 0; k < keySetVar->size(); ++k)
2535 if (keySetVar->asString(k) == id)
2537 GameKeySet = "keys" + string(id.empty() ? "" : "_") + id + ".xml";
2538 RingEditorKeySet = "keys_r2ed" + string(id.empty() ? "" : "_") + id + ".xml";
2539 return;
2544 // else maybe from a previous character?
2545 if (CFile::isExists("save/keys_" + id + ".xml"))
2546 GameKeySet = "keys_" + id + ".xml";
2548 if (CFile::isExists("save/keys_r2ed_" + id + ".xml"))
2549 RingEditorKeySet = "keys_r2ed_" + id + ".xml";
2551 // NB: key file will be copied for real when the new character summary is
2554 REGISTER_ACTION_HANDLER (CAHResetKeysetSelect, "keyset_select");
2560 // *************************** SCENARIO CONTROL WINDOW ***********************
2561 // ***************************************************************************
2562 // helper function for "setScenarioInformation"
2563 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const std::string &text)
2565 CInterfaceElement *result = scenarioWnd->findFromShortId(uiName);
2566 if(result)
2568 CViewText* viewText = dynamic_cast<CViewText*>(result);
2569 if(viewText)
2570 viewText->setTextLocalized(text, false);
2571 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2572 if(editBox)
2573 editBox->setInputString(text);
2577 // helper function for "setScenarioInformation"
2578 static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName, const ucstring &text) // TODO: UTF-8 Lua
2580 setTextField(scenarioWnd, uiName, text.toUtf8());
2582 // helper function for "setScenarioInformation"
2583 static std::string fieldLookup(const vector< pair< string, string > > &values, const std::string &id)
2585 for(uint i=0; i<values.size(); i++)
2587 if (values[i].first == id) return values[i].second;
2589 return "--";
2592 static void setScenarioInformation(CInterfaceGroup* scenarioWnd, const string scenarioName)
2594 vector< pair< string, string > > values;
2595 if(R2::getEditor().isInitialized())
2597 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
2599 else
2601 R2::CScenarioValidator sv;
2602 std::string md5, signature;
2603 sv.setScenarioToLoad(scenarioName, values, md5, signature, false);
2606 setTextField(scenarioWnd, "rules_value_text", fieldLookup(values, "Rules"));
2607 uint levelRange = 0;
2608 uint32 nLevel;
2609 fromString(fieldLookup(values, "Level"), nLevel);
2610 switch(nLevel)
2612 case 20: levelRange = 0; break;
2613 case 50: levelRange = 1; break;
2614 case 100: levelRange = 2; break;
2615 case 150: levelRange = 3; break;
2616 case 200: levelRange = 4; break;
2617 case 250: levelRange = 5; break;
2619 setTextField(scenarioWnd, "level_value_text", CI18N::get("uiRAP_Level" + toString(levelRange)));
2620 setTextField(scenarioWnd, "language_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Language")));
2621 setTextField(scenarioWnd, "type_value_text", CI18N::get("uiR2ED" + fieldLookup(values, "Type")));
2622 setTextField(scenarioWnd, "edit_small_description", fieldLookup(values, "ShortDescription"));
2623 if(R2::getEditor().isInitialized())
2625 setTextField(scenarioWnd, "scenario_value_text", "'" + fieldLookup(values, "Title") + "'");
2630 void getChildrenControls(CInterfaceGroup* group, std::vector<CCtrlBase*> & controls)
2632 for(uint i=0; i<group->getGroups().size(); i++)
2633 getChildrenControls(group->getGroups()[i], controls);
2635 for(uint i=0; i<group->getControls().size(); i++)
2636 controls.push_back(group->getControls()[i]);
2639 inline void setToggleButton(CInterfaceGroup* scenarioWnd, const string & buttonName, bool pushed)
2641 CInterfaceElement * result = scenarioWnd->findFromShortId(buttonName);
2642 if(result)
2644 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
2645 if(group)
2647 result = group->findFromShortId(string("toggle_butt"));
2648 if(result)
2650 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2651 if(baseButton)
2652 baseButton->setPushed(!pushed);
2659 class CAHScenarioControl : public IActionHandler
2661 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2663 nlinfo("CAHScenarioControl called");
2665 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2666 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2667 if(!scenarioWnd) return;
2669 // -------- active some groups in function of Ryzom mode or Edition/Animation mode ----
2670 // active team toggle button?
2671 CInterfaceElement *result = scenarioWnd->findFromShortId(string("invite_team"));
2672 if(result)
2674 CInterfaceGroup* groupTeam = dynamic_cast<CInterfaceGroup*>(result);
2675 if(groupTeam)
2677 bool team = !(R2::getEditor().isInitialized());
2678 if(team)
2679 team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2680 groupTeam->setActive(team);
2684 // set scenario name label
2685 result = scenarioWnd->findFromShortId(string("current_scenario_label_text"));
2686 if(result)
2688 CViewText* viewText = dynamic_cast<CViewText*>(result);
2689 if(viewText)
2691 viewText->setTextLocalized(R2::getEditor().isInitialized() ? "uiR2EDScenarioName" : "uiR2EDScenarioFileName", true);
2695 // ok button tranlation
2696 result = scenarioWnd->findFromShortId(string("ok_button"));
2697 if(result)
2699 CCtrlTextButton* okButton = dynamic_cast<CCtrlTextButton*>(result);
2700 if(okButton)
2702 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
2703 okButton->setHardText(CI18N::get("uiR2EDLaunchScenario"));
2704 else
2705 okButton->setHardText(CI18N::get("uiR2EDApplyScenarioFilters"));
2709 // init current scenario name and parameters
2710 if(!R2::getEditor().isInitialized())
2712 ScenarioFileName.clear();
2714 // empty scenario
2715 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2716 if(result)
2718 CViewText* viewText= dynamic_cast<CViewText*>(result);
2720 if(viewText)
2721 viewText->setText(std::string());
2724 setScenarioInformation(scenarioWnd, "");
2726 // hide description and information?
2727 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2728 if(result)
2729 result->setActive(R2::getEditor().isInitialized());
2731 result = scenarioWnd->findFromShortId(string("description_gr"));
2732 if(result)
2733 result->setActive(R2::getEditor().isInitialized());
2735 // mainlands list
2736 result = scenarioWnd->findFromShortId(string("shards"));
2737 if(result)
2739 CGroupList * shardList = dynamic_cast<CGroupList*>(result);
2740 if(shardList)
2742 shardList->deleteAllChildren();
2744 for(uint i = 0; i < Mainlands.size(); i++)
2746 vector< pair < string, string > > params;
2747 params.clear();
2748 params.push_back(pair<string,string>("id", toString(Mainlands[i].Id)));
2749 params.push_back(pair<string,string>("w", "1024"));
2750 params.push_back(pair<string,string>("tooltip", "uiRingFilterShard"));
2751 CInterfaceGroup *toggleGr = CWidgetManager::getInstance()->getParser()->createGroupInstance("label_toggle_button", shardList->getId(), params);
2752 shardList->addChild(toggleGr);
2753 // set unicode name
2754 CViewText *shardName = dynamic_cast<CViewText *>(toggleGr->getView("button_text"));
2755 if (shardName)
2757 shardName->setTextLocalized(Mainlands[i].Name.toUtf8(), false);
2763 // show/display "back" button
2764 result = scenarioWnd->findFromShortId(string("load_button"));
2765 if(result)
2767 CCtrlBaseButton * loadB = dynamic_cast<CCtrlBaseButton *>(result);
2768 if(loadB)
2770 loadB->setActive(!R2::getEditor().isInitialized());
2774 // fill toggle buttons
2775 if(R2::getEditor().getAccessMode()==R2::CEditor::AccessDM)
2777 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
2778 sessionBrowser.getSessionInfo(sessionBrowser.getCharId(), R2::getEditor().getDMC().getEditionModule().getCurrentAdventureId());
2780 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_sessionInfoResult")))
2782 TRaceFilter & raceFilter = sessionBrowser._LastRaceFilter;
2783 setToggleButton(scenarioWnd, "fyros", raceFilter.checkEnumValue(TRaceFilterEnum::rf_fyros));
2784 setToggleButton(scenarioWnd, "matis", raceFilter.checkEnumValue(TRaceFilterEnum::rf_matis));
2785 setToggleButton(scenarioWnd, "tryker", raceFilter.checkEnumValue(TRaceFilterEnum::rf_tryker));
2786 setToggleButton(scenarioWnd, "zorai", raceFilter.checkEnumValue(TRaceFilterEnum::rf_zorai));
2788 TReligionFilter & religionFilter = sessionBrowser._LastReligionFilter;
2789 setToggleButton(scenarioWnd, "kami", religionFilter.checkEnumValue(TReligionFilterEnum::rf_kami));
2790 setToggleButton(scenarioWnd, "karavan", religionFilter.checkEnumValue(TReligionFilterEnum::rf_karavan));
2791 setToggleButton(scenarioWnd, "neutral", religionFilter.checkEnumValue(TReligionFilterEnum::rf_neutral));
2793 TGuildFilter & guildFilter = sessionBrowser._LastGuildFilter;
2794 setToggleButton(scenarioWnd, "guild_gr", (guildFilter==TGuildFilter::gf_any_player));
2796 TShardFilter & shardFilter = sessionBrowser._LastShardFilter;
2797 for(uint i=0; i<Mainlands.size(); i++)
2798 setToggleButton(scenarioWnd, toString(Mainlands[i].Id), shardFilter.checkEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i)));
2800 TLevelFilter & levelFilter = sessionBrowser._LastLevelFilter;
2801 setToggleButton(scenarioWnd, "20", levelFilter.checkEnumValue(TLevelFilterEnum::lf_a));
2802 setToggleButton(scenarioWnd, "50", levelFilter.checkEnumValue(TLevelFilterEnum::lf_b));
2803 setToggleButton(scenarioWnd, "100", levelFilter.checkEnumValue(TLevelFilterEnum::lf_c));
2804 setToggleButton(scenarioWnd, "150", levelFilter.checkEnumValue(TLevelFilterEnum::lf_d));
2805 setToggleButton(scenarioWnd, "200", levelFilter.checkEnumValue(TLevelFilterEnum::lf_e));
2806 setToggleButton(scenarioWnd, "250", levelFilter.checkEnumValue(TLevelFilterEnum::lf_f));
2808 bool subscriptionClosed = sessionBrowser._LastSubscriptionClosed;
2809 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2810 if(result)
2812 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2813 if(baseButton)
2814 baseButton->setPushed(subscriptionClosed);
2817 bool autoInvite = sessionBrowser._LastAutoInvite;
2818 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2819 if(result)
2821 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2822 if(baseButton)
2823 baseButton->setPushed(!autoInvite);
2826 // description
2827 string description = sessionBrowser._LastDescription;
2828 if(!description.empty())
2830 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2831 if(result)
2833 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2834 if(editBox)
2835 editBox->setInputString(description);
2839 else
2841 nlwarning("getSessionInfo callback return false");
2844 else
2846 result = scenarioWnd->findFromShortId(string("access_players_filter"));
2847 if(result)
2849 CInterfaceGroup* filtersGroup = dynamic_cast<CInterfaceGroup*>(result);
2850 if(filtersGroup)
2852 std::vector<CCtrlBase*> controls;
2853 getChildrenControls(filtersGroup, controls);
2854 for(uint i=0; i<controls.size(); i++)
2856 CCtrlBase* control = controls[i];
2857 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(control);
2858 if(baseButton && (baseButton->getType()==CCtrlBaseButton::ToggleButton))
2859 baseButton->setPushed(false);
2866 REGISTER_ACTION_HANDLER (CAHScenarioControl, "init_scenario_control");
2869 // ***************************************************************************
2870 class CAHScenarioInformation : public IActionHandler
2872 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
2874 nlinfo("CAHScenarioDescription called");
2876 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2877 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2878 if(!scenarioWnd) return;
2880 CInterfaceElement *result = scenarioWnd->findFromShortId(string("scenario_value_text"));
2881 if(result)
2883 CViewText* viewText= dynamic_cast<CViewText*>(result);
2885 if(viewText)
2887 ScenarioFileName = getParam(Params, "ScenarioName");
2888 setScenarioInformation(scenarioWnd, ScenarioFileName);
2890 string scenarioName = ScenarioFileName;
2891 string::size_type posScenarioName = 0;
2892 while(posScenarioName!=string::npos)
2894 scenarioName = scenarioName.substr(posScenarioName==0?posScenarioName:posScenarioName+1);
2895 posScenarioName = scenarioName.find('/');
2897 viewText->setTextLocalized(scenarioName, false);
2901 // active description and information
2902 result = scenarioWnd->findFromShortId(string("scenario_info_prop"));
2903 if(result)
2904 result->setActive(true);
2906 result = scenarioWnd->findFromShortId(string("description_gr"));
2907 if(result)
2908 result->setActive(true);
2911 REGISTER_ACTION_HANDLER (CAHScenarioInformation, "scenario_information");
2913 // ***************************************************************************
2914 class CAHHideCharsFilters : public IActionHandler
2916 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
2918 nlinfo("CAHHideCharsFilters called");
2920 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2921 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2922 if(!scenarioWnd) return;
2924 bool lookingForPlayers = true;
2925 CInterfaceElement *result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
2926 if(result)
2928 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
2929 if(baseButton)
2930 lookingForPlayers = !baseButton->getPushed(); // warning : on / off textures are inverted !!!
2933 result = scenarioWnd->findFromShortId(string("access_body_gr"));
2934 if(result)
2935 result->setActive(lookingForPlayers);
2937 result = scenarioWnd->findFromShortId(string("sep_global_access"));
2938 if(result)
2939 result->setActive(lookingForPlayers);
2941 result = scenarioWnd->findFromShortId(string("auto_invite_label"));
2942 if(result)
2943 result->setActive(lookingForPlayers);
2945 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
2946 if(result)
2947 result->setActive(lookingForPlayers);
2949 result = scenarioWnd->findFromShortId(string("invite_team"));
2950 if(result)
2952 bool team = (NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:TEAM_MEMBER")->getValue8())!=0;
2953 team = (team && !(R2::getEditor().isInitialized()) && lookingForPlayers);
2954 result->setActive(team);
2958 REGISTER_ACTION_HANDLER (CAHHideCharsFilters, "hide_chars_filters");
2960 // ***************************************************************************
2961 class CAHLoadScenario : public IActionHandler
2963 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
2965 nlinfo("CAHLoadScenario called");
2967 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2968 CInterfaceGroup* scenarioWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:r2ed_scenario_control"));
2969 if(!scenarioWnd) return;
2971 CInterfaceElement *result = NULL;
2973 // load scenario
2974 if(!R2::getEditor().isInitialized())
2976 R2::CEditor::setStartingAnimationFilename(ScenarioFileName);
2979 // description
2980 string description;
2981 result = scenarioWnd->findFromShortId(string("edit_small_description"));
2982 if(result)
2984 CGroupEditBox* editBox = dynamic_cast<CGroupEditBox*>(result);
2985 if(editBox)
2986 description = editBox->getInputString();
2989 // races
2990 map<string, bool> races;
2991 races["fyros"] = false;
2992 races["matis"] = false;
2993 races["tryker"] = false;
2994 races["zorai"] = false;
2995 for(map<string, bool>::iterator itRace=races.begin(); itRace!=races.end(); itRace++)
2997 result = scenarioWnd->findFromShortId(itRace->first);
2998 if(result)
3000 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3001 if(group)
3003 result = group->findFromShortId(string("toggle_butt"));
3004 if(result)
3006 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3007 if(baseButton)
3008 itRace->second = !baseButton->getPushed();
3014 // religion
3015 map<string, bool> religions;
3016 religions["kami"] = false;
3017 religions["karavan"] = false;
3018 religions["neutral"] = false;
3019 for(map<string, bool>::iterator itReligion=religions.begin(); itReligion!=religions.end(); itReligion++)
3021 result = scenarioWnd->findFromShortId(itReligion->first);
3022 if(result)
3024 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3025 if(group)
3027 result = group->findFromShortId(string("toggle_butt"));
3028 if(result)
3030 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3031 if(baseButton)
3032 itReligion->second = !baseButton->getPushed();
3038 // guild
3039 bool anyPlayer = false;
3040 result = scenarioWnd->findFromShortId(string("guild_gr"));
3041 if(result)
3043 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3044 if(group)
3046 result = group->findFromShortId(string("toggle_butt"));
3047 if(result)
3049 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3050 if(baseButton)
3051 anyPlayer = !baseButton->getPushed();
3056 // shards
3057 std::vector<bool> shards(Mainlands.size(), false);
3058 for(uint i=0; i<Mainlands.size(); i++)
3060 string firstKey = Mainlands[i].Description.toString();
3062 result = scenarioWnd->findFromShortId(toString(Mainlands[i].Id));
3063 if(result)
3065 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3066 if(group)
3068 result = group->findFromShortId(string("toggle_butt"));
3069 if(result)
3071 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3072 if(baseButton)
3073 shards[i] = !baseButton->getPushed();
3079 // levels
3080 map<string, bool> levels;
3081 levels["20"] = false;
3082 levels["50"] = false;
3083 levels["100"] = false;
3084 levels["150"] = false;
3085 levels["200"] = false;
3086 levels["250"] = false;
3087 for(map<string, bool>::iterator itLevel=levels.begin(); itLevel!=levels.end(); itLevel++)
3089 result = scenarioWnd->findFromShortId(itLevel->first);
3090 if(result)
3092 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup*>(result);
3093 if(group)
3095 result = group->findFromShortId(string("toggle_butt"));
3096 if(result)
3098 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3099 if(baseButton)
3100 itLevel->second = !baseButton->getPushed();
3106 // global access
3107 bool globalAccess = false;
3108 result = scenarioWnd->findFromShortId(string("global_access_toggle_butt"));
3109 if(result)
3111 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3112 if(baseButton)
3113 globalAccess = !baseButton->getPushed();
3116 // auto invite
3117 bool autoInvite = false;
3118 result = scenarioWnd->findFromShortId(string("auto_invite_toggle_butt"));
3119 if(result)
3121 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3122 if(baseButton)
3123 autoInvite = !baseButton->getPushed();
3126 // invite your team
3127 bool inviteTeam = false;
3128 result = scenarioWnd->findFromShortId(string("team_toggle_butt"));
3129 if(result)
3131 CCtrlBaseButton * baseButton = dynamic_cast<CCtrlBaseButton*>(result);
3132 if(baseButton)
3133 inviteTeam = !baseButton->getPushed();
3136 bool launchScenarioFromRingAccessPoint = false;
3138 vector< pair< string, string > > values;
3139 if(R2::getEditor().isInitialized())
3141 values = R2::getEditor().getDMC().getEditionModule().getScenarioHeader();
3143 else
3145 R2::CScenarioValidator sv;
3146 std::string md5, signature;
3147 sv.setScenarioToLoad(ScenarioFileName, values, md5, signature, false);
3148 launchScenarioFromRingAccessPoint = true;
3151 string rules, level, title;
3152 string initialIsland, initialEntryPoint, initialSeason;
3153 std::string lang, scenarioType;
3154 std::string otherCharAccess;
3155 std::string nevraxScenario = "0";
3156 std::string trialAllowed = "0";
3157 for(uint i=0; i<values.size(); i++)
3159 std::pair<std::string, std::string> pair = values[i];
3161 if(pair.first == "Rules") rules = pair.second;
3162 else if(pair.first == "Level") level = pair.second;
3163 else if(pair.first == "Title") title = pair.second;
3164 else if(pair.first == "InitialIsland") initialIsland = pair.second;
3165 else if(pair.first == "InitialEntryPoint") initialEntryPoint = pair.second;
3166 else if(pair.first == "InitialSeason") initialSeason = pair.second;
3167 else if(pair.first == "Language") lang = pair.second;
3168 else if(pair.first == "Type") scenarioType = pair.second;
3169 else if(pair.first == "OtherCharAccess") otherCharAccess = pair.second;
3170 else if(pair.first == "NevraxScenario") nevraxScenario = pair.second;
3171 else if(pair.first == "TrialAllowed") trialAllowed = pair.second;
3174 uint nLevel;
3175 fromString(level, nLevel);
3176 R2::TSessionLevel sessionLevel = R2::TSessionLevel::TValues(nLevel/50 + 1);
3178 // ---- fix for old scenarii
3179 if (lang == "French")
3180 lang = "fr";
3181 else if (lang == "German" || lang == "Deutsch")
3182 lang = "de";
3183 else //if (lang == "English")
3184 lang = "en";
3186 if (nlstricmp(scenarioType, "Roleplay") == 0 || nlstricmp(scenarioType, "Role play") == 0)
3187 scenarioType = "so_story_telling";
3188 else if (nlstricmp(scenarioType, "Combat") == 0)
3189 scenarioType = "so_hack_slash";
3190 // --------------------------
3192 TRuleType ruleType(TRuleType::rt_strict);
3193 if(rules==CI18N::get("uiR2EDliberal"))
3194 ruleType = TRuleType(TRuleType::rt_liberal);
3195 else if(rules == CI18N::get("uiR2EDstrict"))
3196 ruleType = TRuleType(TRuleType::rt_strict);
3197 volatile static bool override = false;
3198 if (override)
3200 if(rules== "Masterless")
3201 ruleType = TRuleType(TRuleType::rt_liberal);
3202 else if(rules == "Mastered")
3203 ruleType = TRuleType(TRuleType::rt_strict);
3206 TRaceFilter raceFilter;
3207 if(races["fyros"])
3208 raceFilter.setEnumValue(TRaceFilterEnum::rf_fyros);
3209 if(races["matis"])
3210 raceFilter.setEnumValue(TRaceFilterEnum::rf_matis);
3211 if(races["tryker"])
3212 raceFilter.setEnumValue(TRaceFilterEnum::rf_tryker);
3213 if(races["zorai"])
3214 raceFilter.setEnumValue(TRaceFilterEnum::rf_zorai);
3216 TReligionFilter religionFilter;
3217 if(religions["kami"])
3218 religionFilter.setEnumValue(TReligionFilterEnum::rf_kami);
3219 if(religions["karavan"])
3220 religionFilter.setEnumValue(TReligionFilterEnum::rf_karavan);
3221 if(religions["neutral"])
3222 religionFilter.setEnumValue(TReligionFilterEnum::rf_neutral);
3224 TGuildFilter guildFilter(anyPlayer?TGuildFilter::gf_any_player:TGuildFilter::gf_only_my_guild);
3226 TShardFilter shardFilter;
3227 for (uint i = 0; i < shards.size(); ++i)
3229 if (shards[i]) shardFilter.setEnumValue((RSMGR::TShardFilterEnum::TValues) (1<<i));
3232 TLevelFilter levelFilter;
3233 if(levels["20"])
3234 levelFilter.setEnumValue(TLevelFilterEnum::lf_a);
3235 if(levels["50"])
3236 levelFilter.setEnumValue(TLevelFilterEnum::lf_b);
3237 if(levels["100"])
3238 levelFilter.setEnumValue(TLevelFilterEnum::lf_c);
3239 if(levels["150"])
3240 levelFilter.setEnumValue(TLevelFilterEnum::lf_d);
3241 if(levels["200"])
3242 levelFilter.setEnumValue(TLevelFilterEnum::lf_e);
3243 if(levels["250"])
3244 levelFilter.setEnumValue(TLevelFilterEnum::lf_f);
3246 uint32 charId = 0;
3247 if (!ClientCfg.Local)
3248 charId = (NetMngr.getLoginCookie().getUserId()<< 4) + (uint32) PlayerSelectedSlot;
3250 CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance();
3252 if(R2::getEditor().getAccessMode() != R2::CEditor::AccessDM)
3254 bool noob = NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IS_NEWBIE")->getValueBool();
3255 if (FreeTrial && noob && (nevraxScenario != "1" || trialAllowed != "1"))
3257 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3258 if (pVT != NULL)
3259 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3260 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3262 return;
3267 if(R2::getEditor().getAccessMode()!=R2::CEditor::AccessDM)
3269 if (launchScenarioFromRingAccessPoint)
3271 // hibernate Edit Session if active
3272 sessionBrowser.hibernateEditSession(charId);
3273 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3275 nlwarning("hibernateEditSession callback return false");
3280 // schedule session
3281 bool launchSuccess = true;
3282 sessionBrowser.scheduleSession(charId, TSessionType::st_anim,
3283 title, description, sessionLevel,
3284 /*TAccessType::at_public,*/ ruleType, TEstimatedDuration::et_medium, 0, TAnimMode::am_dm,
3285 raceFilter, religionFilter, guildFilter, shardFilter, levelFilter, lang, RSMGR::TSessionOrientation(scenarioType),
3286 !globalAccess, autoInvite);
3288 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_scheduleSessionResult")))
3290 if(sessionBrowser._LastScheduleSessionResult==0)
3292 // start session
3293 sessionBrowser.startSession(sessionBrowser._LastScheduleSessionCharId,
3294 sessionBrowser._LastScheduleSessionId);
3296 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3299 if (launchScenarioFromRingAccessPoint)
3301 if (!initialIsland.empty() && !initialEntryPoint.empty() && !initialSeason.empty())
3303 sessionBrowser.setSessionStartParams(charId, sessionBrowser._LastScheduleSessionId, initialIsland, initialEntryPoint, initialSeason);
3307 TSessionPartStatus sessionStatus;
3308 if(ruleType==TRuleType::rt_liberal)
3309 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_play_invited);
3310 else
3311 sessionStatus = TSessionPartStatus(TSessionPartStatus::sps_anim_invited);
3313 // invite player
3314 sessionBrowser.inviteCharacter(
3315 sessionBrowser._LastScheduleSessionCharId,
3316 sessionBrowser._LastScheduleSessionId,
3317 sessionBrowser._LastScheduleSessionCharId,
3318 sessionStatus.toString());
3320 if(sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3322 // request session
3323 FarTP.requestFarTPToSession(sessionBrowser._LastScheduleSessionId, PlayerSelectedSlot, CFarTP::JoinSession,
3324 !R2::getEditor().isInitialized());
3326 else
3328 nlwarning("inviteCharacter callback return false");
3331 if (sessionBrowser._LastInvokeResult != 0)
3333 nlwarning("inviteCharacter callback use error values %d", sessionBrowser._LastInvokeResult);
3336 if(sessionBrowser._LastInvokeResult == 14)
3338 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3339 if (pVT != NULL)
3340 pVT->setTextLocalized("uiRingWarningFreeTrial", true);
3341 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3345 // invite team
3346 if(inviteTeam)
3348 for (uint i = 0 ; i < 8 ; ++i)
3350 uint32 val = NLGUI::CDBManager::getInstance()->getDbProp(NLMISC::toString("SERVER:GROUP:%d:NAME",i))->getValue32();
3351 if(val!=0)
3353 STRING_MANAGER::CStringManagerClient *pSMC = STRING_MANAGER::CStringManagerClient::instance();
3354 string res;
3355 if (pSMC->getString(val,res))
3357 string charName = CEntityCL::removeTitleAndShardFromName(res);
3358 sessionBrowser.inviteCharacterByName(sessionBrowser._LastScheduleSessionCharId, charName);
3360 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3362 nlwarning("inviteCharacterByName callback return false");
3365 if(sessionBrowser._LastInvokeResult == 14)
3367 CViewText* pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:warning_free_trial:text"));
3368 if (pVT != NULL)
3369 pVT->setTextLocalized("uiRingWarningInviteFreeTrial", true);
3370 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_free_trial");
3377 else
3379 nlwarning("startSession callback return false");
3380 launchSuccess = false;
3383 else if(sessionBrowser._LastScheduleSessionResult==10)
3385 pIM->messageBoxWithHelp(CI18N::get("uiRingWarningBanishedPlayer"));
3387 else
3389 launchSuccess=false;
3392 else
3394 nlwarning("scheduleSession callback return false");
3395 launchSuccess = false;
3398 if(!launchSuccess)
3400 pIM->messageBoxWithHelp(CI18N::get("uiRingLaunchScenarioError"));
3402 else
3404 scenarioWnd->setActive(false);
3407 else
3409 // update session
3410 sessionBrowser.updateSessionInfo(charId, sessionBrowser._LastScheduleSessionId, title, 0, description, sessionLevel,
3411 /*TAccessType::at_public, */TEstimatedDuration::et_medium, 0, raceFilter, religionFilter,
3412 guildFilter, shardFilter, levelFilter, !globalAccess, autoInvite, lang, RSMGR::TSessionOrientation(scenarioType));
3414 if(!sessionBrowser.waitOneMessage(sessionBrowser.getMessageName("on_invokeResult")))
3416 nlwarning("updateSessionInfo callback return false");
3417 pIM->messageBoxWithHelp(CI18N::get("uiRingUpdateScenarioFiltersError"));
3419 else
3421 scenarioWnd->setActive(false);
3426 REGISTER_ACTION_HANDLER (CAHLoadScenario, "load_scenario");
3429 // ***************************************************************************
3430 class CAHOpenRingSessions : public IActionHandler
3432 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3434 if(!R2::getEditor().isInitialized())
3436 CInterfaceManager *pIM = CInterfaceManager::getInstance();
3437 CInterfaceGroup* ringSessionsWnd = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:ring_sessions"));
3438 if(!ringSessionsWnd) return;
3439 ringSessionsWnd->setActive(true);
3443 REGISTER_ACTION_HANDLER (CAHOpenRingSessions, "open_ring_sessions");
3445 // ***************************************************************************
3446 class CAHInitImportCharacter : public IActionHandler
3448 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3450 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3451 if (!list)
3453 nlwarning("element " GROUP_LIST_CHARACTER " not found probably bad outgame.xml");
3454 return;
3457 // retrieve saved files
3458 std::vector<string> savedCharacters;
3459 CPath::getPathContent("save/", false, false, true, savedCharacters);
3461 CInterfaceGroup *newLine;
3462 CInterfaceGroup *prevLine = NULL;
3464 for (uint i = 0; i < savedCharacters.size(); ++i)
3466 // search saved characters only
3467 if (testWildCard(CFile::getFilename(savedCharacters[i]), "character_*.save"))
3469 const std::string id = CFile::getFilenameWithoutExtension(savedCharacters[i]).substr(strlen("character_"));
3470 if (id.empty())
3471 continue;
3473 std::vector<pair<string, string>> params;
3474 params.clear();
3475 params.push_back(std::pair<string, string>("id", id));
3476 // adjust ref
3477 if (list->getNumGroup() > 0)
3478 params.push_back(std::pair<string, string>("posref", "BL TL"));
3480 newLine = CWidgetManager::getInstance()->getParser()->createGroupInstance("t_import", GROUP_LIST_CHARACTER, params);
3481 if (newLine)
3483 CViewText *text = dynamic_cast<CViewText*>(newLine->getView("name"));
3484 if (text)
3485 text->setText(string(savedCharacters[i]));
3487 // first button is pushed
3488 CCtrlButton *button = dynamic_cast<CCtrlButton*>(newLine->getCtrl("but"));
3489 if (button && list->getNumGroup() == 0)
3490 button->setPushed(true);
3492 // add to the list now
3493 newLine->setParent(list);
3494 newLine->setParentSize(list);
3495 newLine->setParentPos(prevLine);
3497 list->addGroup(newLine);
3499 prevLine = newLine;
3503 // none case
3504 if (list->getNumGroup() == 0)
3505 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(3)");
3507 list->invalidateCoords();
3510 REGISTER_ACTION_HANDLER( CAHInitImportCharacter, "import_char_init" );
3512 // ***************************************************************************
3513 class CAHResetImportCharacter : public IActionHandler
3515 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3517 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3518 if (list)
3519 list->clearGroups();
3521 if (!ImportCharacter.empty())
3522 ImportCharacter = "";
3525 REGISTER_ACTION_HANDLER( CAHResetImportCharacter, "import_char_reset" );
3527 // ***************************************************************************
3528 class CAHSelectImportCharacter : public IActionHandler
3530 virtual void execute (CCtrlBase *pCaller, const std::string &Params)
3532 struct CUnpush : public CInterfaceElementVisitor
3534 CCtrlBase *Ref;
3535 virtual void visitCtrl(CCtrlBase *ctrl)
3537 if (ctrl == Ref) return;
3538 CCtrlBaseButton *but = dynamic_cast<CCtrlBaseButton*>(ctrl);
3539 if (but)
3541 but->setPushed(false);
3545 CInterfaceGroup *list = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(GROUP_LIST_CHARACTER));
3546 if (!list)
3547 return;
3549 // unselect
3550 if (Params.empty())
3552 CUnpush unpusher;
3553 unpusher.Ref = pCaller;
3554 list->visit(&unpusher);
3557 // now select
3558 std::string name;
3559 if (Params.empty())
3561 CCtrlButton *pCB = dynamic_cast<CCtrlButton*>(pCaller);
3562 if (!pCB)
3563 return;
3565 std::string id = pCB->getId();
3566 id = id.substr(0, id.rfind(':'));
3568 if (!fromString(id.substr(id.rfind(':')+1, id.size()), name))
3569 return;
3571 pCB->setPushed(true);
3573 else
3574 if (!fromString(Params, name))
3575 return;
3577 ImportCharacter = "";
3578 // check filename and store
3579 if (CFile::fileExists(toString("save/character_%s.save", name.c_str())))
3580 ImportCharacter = name;
3583 REGISTER_ACTION_HANDLER( CAHSelectImportCharacter, "import_char_select" );
3585 // ***************************************************************************
3586 class CAHImportCharacter : public IActionHandler
3588 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
3590 if (ImportCharacter.empty())
3591 return;
3593 if (!CFile::fileExists(toString("save/character_%s.save", ImportCharacter.c_str())))
3594 return;
3596 bool success = false;
3598 CIFile fd;
3599 CCharacterSummary CS;
3600 // use temporary file until close()
3601 if (fd.open(toString("save/character_%s.save", ImportCharacter.c_str())))
3605 CS.serial(fd);
3606 SCharacter3DSetup::setupDBFromCharacterSummary("UI:TEMP:CHAR3D", CS);
3608 // validate import
3609 CDBManager::getInstance()->getDbProp("UI:TEMP:IMPORT")->setValue32(1);
3610 success = true;
3612 catch (const EStream &e)
3614 nlwarning(e.what());
3616 fd.close();
3618 else
3619 nlwarning("Failed to open file: save/character_%s.save", ImportCharacter.c_str());
3621 // user notification
3622 if (!success)
3623 CLuaManager::getInstance().executeLuaScript("outgame:procCharselNotifaction(2)");
3624 else
3625 CAHManager::getInstance()->runActionHandler("proc", NULL, "proc_charsel_create_new");
3628 REGISTER_ACTION_HANDLER( CAHImportCharacter, "import_char" );
3630 // ***************************************************************************
3631 class CAHExportCharacter : public IActionHandler
3633 virtual void execute (CCtrlBase * /* pCaller */, const std::string &Params)
3635 if (Params.empty())
3636 return;
3638 sint32 slot = -1;
3639 if (!fromString(getParam(Params, "slot"), slot))
3640 return;
3642 if (slot >= CharacterSummaries.size() || slot < 0)
3643 return;
3645 // retrieve infos
3646 CCharacterSummary &CS = CharacterSummaries[slot];
3647 if (CS.Name.empty())
3648 return;
3650 // extract name
3651 const std::string name = buildPlayerNameForSaveFile(CS.Name.toUtf8());
3653 COFile fd;
3654 bool success = false;
3655 // use temporary file until close()
3656 if (fd.open(toString("save/character_%s.save", name.c_str()), false, false, true))
3660 fd.serial(CS);
3661 fd.flush();
3662 // validate
3663 success = true;
3665 catch (const EStream &e)
3667 nlwarning(e.what());
3669 fd.close();
3671 else
3672 nlwarning("Failed to open file: save/character_%s.save", name.c_str());
3674 const uint8 val = (success == true) ? 0 : 1;
3675 // user notification
3676 CLuaManager::getInstance().executeLuaScript(toString("outgame:procCharselNotifaction(%i)", val));
3679 REGISTER_ACTION_HANDLER( CAHExportCharacter, "export_char" );