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