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