1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "../string_manager_client.h"
26 #include "people_interraction.h"
27 #include "nel/gui/interface_expr.h"
28 #include "interface_manager.h"
29 #include "nel/gui/action_handler.h"
30 #include "action_handler_misc.h"
31 #include "chat_window.h"
32 #include "../entity_animation_manager.h"
33 #include "nel/gui/group_editbox.h"
34 #include "nel/gui/group_menu.h"
35 #include "../client_chat_manager.h"
36 #include "../string_manager_client.h"
37 #include "nel/gui/interface_expr.h"
38 #include "nel/gui/ctrl_button.h"
39 #include "nel/gui/ctrl_text_button.h"
40 #include "filtered_chat_summary.h"
41 #include "input_handler_manager.h"
42 #include "../user_entity.h"
43 #include "../entities.h"
44 #include "../net_manager.h"
45 #include "../connection.h"
46 #include "nel/gui/group_tab.h"
47 #include "guild_manager.h"
49 #include "game_share/entity_types.h"
51 #include <nel/misc/command.h>
52 #include <nel/misc/rgba.h>
53 #include <nel/misc/i18n.h>
59 using namespace NLMISC
;
68 extern CEntityAnimationManager
*EAM
;
69 extern CClientChatManager ChatMngr
;
70 extern NLMISC::CLog g_log
;
76 CPeopleInterraction PeopleInterraction
;
79 static const string MAIN_CHAT_SOURCE_MENU
= "ui:interface:main_chat_source_menu";
80 static const string USER_CHAT_SOURCE_MENU
= "ui:interface:user_chat_source_menu";
81 static const string STD_CHAT_SOURCE_MENU
= "ui:interface:std_chat_source_menu";
82 static const string NEW_PARTY_CHAT_WINDOW
= "ui:interface:create_new_party_chat";
84 NLMISC::CRefPtr
<CChatWindow
> ChatWindowForFilter
;
86 static const sint PARTY_CHAT_SPAWN_DELTA
= 20; // to avoid that all party chat appear at the same position, a random value is added
88 //////////////////////////////////
89 // STATIC FUNCTIONs DECLARATION //
90 //////////////////////////////////
92 /** Display an error msg in the system info window, and also in the last window that triggered the command (so that the user is sure to see it)
94 static void displayVisibleSystemMsg(const std::string
&msg
, const string
&cat
= "CHK");
97 //////////////////////////////
98 // HANDLER FOR CHAT WINDOWS //
99 //////////////////////////////
101 // handler to manage user entry in party chat windows
103 struct CPartyChatEntryHandler
: public IChatWindowListener
105 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
109 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::player
, 0);
113 // TODO GAMEDEV : manage entry in the party chat
120 // handler to manage user entry in 'around me' window
121 struct CAroundMeEntryHandler
: public IChatWindowListener
123 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
127 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::arround
, 0);
131 // process msg as usual
132 ChatMngr
.setChatMode(CChatGroup::arround
);
138 // handler to manage user entry in 'region' window
139 struct CRegionEntryHandler
: public IChatWindowListener
141 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
145 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::region
, 0);
149 // process msg as usual
150 ChatMngr
.setChatMode(CChatGroup::region
);
156 // handler to manage user entry in 'universe' window
157 struct CUniverseEntryHandler
: public IChatWindowListener
159 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
163 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::universe
, 0);
167 // process msg as usual
168 ChatMngr
.setChatMode(CChatGroup::universe
);
174 // handler to manage user entry in 'guild chat' window
175 struct CGuildChatEntryHandler
: public IChatWindowListener
177 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
181 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::guild
, 0);
185 ChatMngr
.setChatMode(CChatGroup::guild
);
191 // handler to manage user entry in 'team chat' window
192 struct CTeamChatEntryHandler
: public IChatWindowListener
194 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
198 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::team
, 0);
202 ChatMngr
.setChatMode(CChatGroup::team
);
203 ChatMngr
.chat(msg
, true);
208 // handler to manage user entry in a 'talk with friend' window
209 struct CFriendTalkEntryHandler
: public IChatWindowListener
211 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
215 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::player
, 0);
220 // TODO GAMEDEV : send msg to other player
225 // handler to manage user entry in a debug console window
226 struct CDebugConsoleEntryHandler
: public IChatWindowListener
228 virtual void msgEntered(const string
&msg
, CChatWindow
* /* chatWindow */)
230 NLMISC::ICommand::execute( msg
, g_log
);
234 // handler to manager user entry in a Dynamic Chat
235 struct CDynamicChatEntryHandler
: public IChatWindowListener
239 CDynamicChatEntryHandler()
244 virtual void msgEntered(const string
&msg
, CChatWindow
*chatWindow
)
248 chatWindow
->displayMessage(msg
, CRGBA::White
, CChatGroup::dyn_chat
, DbIndex
);
252 ChatMngr
.setChatMode(CChatGroup::dyn_chat
, ChatMngr
.getDynamicChannelIdFromDbIndex(DbIndex
));
260 static CPartyChatEntryHandler PartyChatEntryHandler
;
261 static CAroundMeEntryHandler AroundMeEntryHandler
;
262 static CRegionEntryHandler RegionEntryHandler
;
263 static CUniverseEntryHandler UniverseEntryHandler
;
264 static CGuildChatEntryHandler GuildChatEntryHandler
;
265 static CTeamChatEntryHandler TeamChatEntryHandler
;
266 static CFriendTalkEntryHandler FriendTalkEntryHandler
;
267 static CDebugConsoleEntryHandler DebugConsoleEntryHandler
;
268 static CDynamicChatEntryHandler DynamicChatEntryHandler
[CChatGroup::MaxDynChanPerPlayer
];
271 //////////////////////
272 // MEMBER FUNCTIONS //
273 //////////////////////
275 //===========================================================================================================
276 void CChatStdInput::registerListeningWindow(CChatWindow
*cw
)
279 Guild
.addListeningWindow(cw
);
280 Team
.addListeningWindow(cw
);
281 Tell
.addListeningWindow(cw
);
282 AroundMe
.addListeningWindow(cw
);
283 Region
.addListeningWindow(cw
);
284 SystemInfo
.addListeningWindow(cw
);
285 Universe
.addListeningWindow(cw
);
289 //===========================================================================================================
290 CPeopleInterraction::CPeopleInterraction() : Region(NULL
),
299 for(uint i
=0;i
<CChatGroup::MaxDynChanPerPlayer
;i
++)
301 DynamicChat
[i
]= NULL
;
306 //===========================================================================================================
307 void CPeopleInterraction::release()
309 ChatInput
.Tell
.removeListeningPeopleList(&FriendList
);
310 ChatInput
.Tell
.removeListeningPeopleList(&TeamList
);
311 ChatInput
.Team
.removeListeningPeopleList(&TeamList
);
313 CChatWindowManager
&cwm
= getChatWndMgr();
316 if (Region
) cwm
.removeChatWindow(Region
);
317 if (Universe
) cwm
.removeChatWindow(Universe
);
318 if (TeamChat
) cwm
.removeChatWindow(TeamChat
);
319 if (GuildChat
) cwm
.removeChatWindow(GuildChat
);
320 if (SystemInfo
) cwm
.removeChatWindow(SystemInfo
);
321 TheUserChat
.release();
322 if (DebugInfo
) cwm
.removeChatWindow(DebugInfo
);
323 // if (TellWindow) cwm.removeChatWindow(TellWindow);
335 // TellWindow = NULL;
337 for(uint i
=0;i
<CChatGroup::MaxDynChanPerPlayer
;i
++)
339 if(DynamicChat
[i
]) cwm
.removeChatWindow(DynamicChat
[i
]);
340 DynamicChat
[i
]= NULL
;
343 removeAllPartyChat();
347 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
349 UserChat
[k
].release();
351 uint numCW
= cwm
.getNumChatWindow();
354 nlwarning("%d chat windows have not been deleted", (int) numCW
);
355 uint numCW
= cwm
.getNumChatWindow();
356 for(uint k
= 0; k
< numCW
; ++k
)
358 nlwarning("Window %d : %s", (int) k
, (cwm
.getChatWindowByIndex(k
)->getTitle()).c_str());
363 //===========================================================================================================
364 void CPeopleInterraction::removeAllPartyChat()
366 CChatWindowManager
&cwm
= getChatWndMgr();
367 for(std::vector
<CPartyChatInfo
>::iterator it
= PartyChats
.begin(); it
!= PartyChats
.end(); ++it
)
369 if (it
->Window
) cwm
.removeChatWindow(it
->Window
);
373 // remove filtered chats
374 //cwm.removeChatWindow(MainChat.Window);
375 //MainChat.Window = NULL;
376 cwm
.removeChatWindow(ChatGroup
.Window
);
377 ChatGroup
.Window
= NULL
;
378 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
380 if (UserChat
[k
].Window
)
382 cwm
.removeChatWindow(UserChat
[k
].Window
);
383 UserChat
[k
].Window
= NULL
;
389 //===========================================================================================================
390 bool CPeopleInterraction::isUserChat(CChatWindow
*cw
) const
392 // if (cw == MainChat.Window) return true;
393 if (cw
== ChatGroup
.Window
) return true;
394 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
396 if (UserChat
[k
].Window
== cw
) return true;
401 //===========================================================================================================
402 void CPeopleInterraction::init()
404 // create chat windows
405 // todo : internationnalization
406 createAroundMeWindow();
407 createRegionWindow();
408 createUniverseWindow();
413 createDynamicChats();
416 //createTellWindow();
422 // main chat should be created after other windows, because it relies on them to receive its messages
425 // init the standard inputs
430 //===========================================================================================================
431 void CPeopleInterraction::initAfterLoad()
433 /* activate the USER chat per default.
434 Important: we must do it after ChatGroup.Window var init, DB color init etc...
435 because the latest are used in chat_group_filter ActionHandler
437 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
439 pCGW
->setTabIndex(5);
443 //===========================================================================================================
444 void CPeopleInterraction::initStdInputs()
448 ChatInput
.AroundMe
.addListeningWindow (ChatGroup
.Window
);
449 ChatInput
.Region
.addListeningWindow (ChatGroup
.Window
);
450 ChatInput
.Team
.addListeningWindow (ChatGroup
.Window
);
451 ChatInput
.Guild
.addListeningWindow (ChatGroup
.Window
);
452 ChatInput
.Tell
.addListeningWindow (ChatGroup
.Window
);
453 ChatInput
.SystemInfo
.addListeningWindow (ChatGroup
.Window
);
454 ChatInput
.Universe
.addListeningWindow (ChatGroup
.Window
);
457 ChatInput
.AroundMe
.addListeningWindow(AroundMe
.Window
);
460 ChatInput
.Region
.addListeningWindow(Region
);
463 ChatInput
.Universe
.addListeningWindow(Universe
);
466 ChatInput
.Team
.addListeningWindow(TeamChat
);
469 ChatInput
.Guild
.addListeningWindow(GuildChat
);
472 ChatInput
.SystemInfo
.addListeningWindow(SystemInfo
);
475 ChatInput
.DebugInfo
.addListeningWindow(DebugInfo
);
477 if (TheUserChat
.Window
)
479 ChatInput
.AroundMe
.addListeningWindow(TheUserChat
.Window
);
480 ChatInput
.Region
.addListeningWindow(TheUserChat
.Window
);
481 ChatInput
.Team
.addListeningWindow(TheUserChat
.Window
);
482 ChatInput
.Guild
.addListeningWindow(TheUserChat
.Window
);
483 ChatInput
.Universe
.addListeningWindow (TheUserChat
.Window
);
484 // Don't add the system info by default
486 for(i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
488 ChatInput
.DynamicChat
[i
].addListeningWindow(TheUserChat
.Window
);
492 ChatInput
.Tell
.addListeningPeopleList(&FriendList
);
493 ChatInput
.Tell
.addListeningPeopleList(&TeamList
);
494 ChatInput
.Team
.addListeningPeopleList(&TeamList
);
497 for(i
=0;i
<CChatGroup::MaxDynChanPerPlayer
;i
++)
499 ChatInput
.DynamicChat
[i
].addListeningWindow(ChatGroup
.Window
);
501 ChatInput
.DynamicChat
[i
].addListeningWindow(DynamicChat
[i
]);
505 //===========================================================================================================
506 void CPeopleInterraction::createTeamList()
508 // temp to test people list before it is connected to the server
509 CPeopleListDesc peopleListDesc
;
510 //peopleListDesc.FatherContainer = "ui:interface:communication";
511 peopleListDesc
.PeopleListTitle
= "uiTeamTitle";
512 peopleListDesc
.Id
= "team_list";
513 peopleListDesc
.ContactType
= CPeopleListDesc::Team
/* CPeopleListDesc::Contact*/;
514 peopleListDesc
.BaseContainerTemplateName
= "people_list_container";
515 peopleListDesc
.Localize
= true;
516 peopleListDesc
.Savable
= true;
517 peopleListDesc
.AHOnActive
= "proc";
518 peopleListDesc
.AHOnActiveParams
= "team_list_proc_active";
519 peopleListDesc
.AHOnDeactive
= "proc";
520 peopleListDesc
.AHOnDeactiveParams
= "team_list_proc_deactive";
521 peopleListDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
523 TeamList
.create(peopleListDesc
, NULL
); // &chatDesc // create the team list with a chat box in it
524 TeamList
.setMenu("ui:interface:sort_menu");
525 // Special case for team : each entry is connected to the database so we create all team member at once
526 for(uint k
= 0; k
< MaxNumPeopleInTeam
; ++k
)
528 TeamList
.addPeople(NLMISC::toString(k
), k
);
531 TeamList
.setPeopleMenu("ui:interface:team_member_menu");
532 TeamList
.setMenu("ui:interface:team_chat_member_menu");
534 // Open/Close team list when at least one / no team mate
535 // NB: use an intermediate temp var, to avoid show of the window each time a new team member enters
536 string sExpr
= "@UI:VARIABLES:IS_TEAM_PRESENT";
537 string sAction
= "set";
539 string sParams
= "target_property=ui:interface:team_list:active|value=@UI:VARIABLES:IS_TEAM_PRESENT";
543 CInterfaceLink
*il
= new CInterfaceLink
;
544 vector
<CInterfaceLink::CTargetInfo
> targets
;
545 vector
<CInterfaceLink::CCDBTargetInfo
> cdbTargets
;
546 il
->init(targets
, cdbTargets
, sExpr
, sAction
, sParams
, sCond
, TeamChat
->getContainer());
550 //===========================================================================================================
551 void CPeopleInterraction::createFriendList()
553 // create friend list
554 CPeopleListDesc peopleListDesc
;
555 peopleListDesc
.FatherContainer
= "ui:interface:contact_list";
556 peopleListDesc
.PeopleListTitle
= "uiFriendList";
557 peopleListDesc
.Id
= "friend_list";
558 peopleListDesc
.BaseContainerTemplateName
= "people_list_container_with_add_edit_box";
559 peopleListDesc
.ContactType
= CPeopleListDesc::Contact
;
560 peopleListDesc
.Localize
= true;
562 FriendList
.create(peopleListDesc
);
563 FriendList
.setPeopleMenuEx("ui:interface:friend_list_menu_offline_unblocked",
564 "ui:interface:friend_list_menu_online_unblocked",
565 "ui:interface:friend_list_menu_online_abroad_unblocked",
566 "ui:interface:friend_list_menu_offline_blocked",
567 "ui:interface:friend_list_menu_online_blocked",
568 "ui:interface:friend_list_menu_online_abroad_blocked"
570 FriendList
.setMenu("ui:interface:sort_menu");
574 //===========================================================================================================
575 void CPeopleInterraction::createIgnoreList()
577 // create ignore list
578 CPeopleListDesc peopleListDesc
;
579 peopleListDesc
.FatherContainer
= "ui:interface:contact_list";
580 peopleListDesc
.PeopleListTitle
= "uiIgnoreList";
581 peopleListDesc
.Id
= "ignore_list";
582 peopleListDesc
.BaseContainerTemplateName
= "people_list_container_with_add_edit_box";
583 peopleListDesc
.ContactType
= CPeopleListDesc::Ignore
;
584 peopleListDesc
.Localize
= true;
586 IgnoreList
.create(peopleListDesc
);
588 IgnoreList
.setPeopleMenu("ui:interface:ignore_list_menu");
589 IgnoreList
.setMenu("ui:interface:sort_menu");
592 //===========================================================================================================
593 void CPeopleInterraction::createSystemInfo()
595 CChatWindowDesc chatDesc
;
596 chatDesc
.FatherContainer
= "ui:interface";
597 chatDesc
.Title
= "uiSystemInfoTitle";
598 chatDesc
.Listener
= NULL
;
599 chatDesc
.Savable
= true;
600 chatDesc
.Localize
= true;
601 chatDesc
.ChatTemplate
="system_info_id";
602 chatDesc
.Id
= "system_info";
603 chatDesc
.AHOnCloseButton
= "proc";
604 chatDesc
.AHOnCloseButtonParams
= "sysinfo_chat_proc_close";
606 SystemInfo
= getChatWndMgr().createChatWindow(chatDesc
);
607 if (!SystemInfo
) return;
608 SystemInfo
->setMenu("ui:interface:base_chat_box_menu");
611 //===========================================================================================================
612 void CPeopleInterraction::createDebugInfo()
614 // can only be used by devs and CSR or in local mode
616 if( ClientCfg
.Local
|| hasPrivilegeDEV() || hasPrivilegeSGM() )
619 CChatWindowDesc chatDesc
;
620 chatDesc
.FatherContainer
= "ui:interface";
621 chatDesc
.Title
= "uiDebugConsole";
622 chatDesc
.Listener
= NULL
;
623 chatDesc
.Savable
= true;
624 chatDesc
.Localize
= true;
625 chatDesc
.Listener
= &DebugConsoleEntryHandler
;
626 chatDesc
.ChatTemplate
="clearable_chat_id";
627 chatDesc
.Id
= "debug_info";
629 DebugInfo
= getChatWndMgr().createChatWindow(chatDesc
);
630 if (!DebugInfo
) return;
631 DebugInfo
->setMenu("ui:interface:base_chat_box_menu");
635 //===========================================================================================================
636 void CPeopleInterraction::createAroundMeWindow()
638 CChatWindowDesc chatDesc
;
639 chatDesc
.FatherContainer
= "ui:interface";
640 chatDesc
.Title
= "uiAroundMeTitle";
641 chatDesc
.Listener
= NULL
;
642 chatDesc
.Localize
= true;
643 chatDesc
.Savable
= true;
644 //chatDesc.ChatTemplate = "around_me_id";
645 chatDesc
.Id
= "around_me";
646 chatDesc
.AHOnCloseButton
= "proc";
647 chatDesc
.AHOnCloseButtonParams
= "around_me_chat_proc_close";
649 AroundMe
.Window
= getChatWndMgr().createChatWindow(chatDesc
);
650 if (!AroundMe
.Window
) return;
651 AroundMe
.Window
->setMenu(STD_CHAT_SOURCE_MENU
);
652 // Configure filter for the main chat. By default, it listen to everything (no party chats : none have been created yet)
653 AroundMe
.Filter
.setTargetGroup(CChatGroup::say
);
654 // associate filter with chat window
655 AroundMe
.Filter
.setChat(AroundMe
.Window
);
659 //===========================================================================================================
660 void CPeopleInterraction::createRegionWindow()
662 // create region window
663 CChatWindowDesc chatDesc
;
664 chatDesc
.FatherContainer
= "ui:interface";
665 chatDesc
.Title
= "uiRegionTitle";
666 chatDesc
.Listener
= &RegionEntryHandler
;
667 chatDesc
.Localize
= true;
668 chatDesc
.Savable
= true;
669 chatDesc
.Id
= "region_chat";
670 chatDesc
.AHOnCloseButton
= "proc";
671 chatDesc
.AHOnCloseButtonParams
= "region_chat_proc_close";
672 chatDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
674 Region
= getChatWndMgr().createChatWindow(chatDesc
);
676 Region
->setMenu(STD_CHAT_SOURCE_MENU
);
680 //===========================================================================================================
681 void CPeopleInterraction::createUniverseWindow()
683 // create universe window
684 CChatWindowDesc chatDesc
;
685 chatDesc
.FatherContainer
= "ui:interface";
686 chatDesc
.Title
= "uiUniverseTitle";
687 chatDesc
.Listener
= &UniverseEntryHandler
;
688 chatDesc
.Localize
= true;
689 chatDesc
.Savable
= true;
690 chatDesc
.Id
= "universe_chat";
691 chatDesc
.AHOnCloseButton
= "proc";
692 chatDesc
.AHOnCloseButtonParams
= "universe_chat_proc_close";
693 chatDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
695 Universe
= getChatWndMgr().createChatWindow(chatDesc
);
696 if (!Universe
) return;
697 Universe
->setMenu(STD_CHAT_SOURCE_MENU
);
701 //===========================================================================================================
702 void CPeopleInterraction::createTellWindow()
704 /*CChatWindowDesc chatDesc;
705 chatDesc.FatherContainer = "ui:interface";
706 chatDesc.Title = "uiTellWindow";
707 chatDesc.Listener = NULL;
708 chatDesc.Savable = true;
709 chatDesc.Localize = true;
710 chatDesc.Id = "tell";
711 chatDesc.ChatTemplate ="chat_no_eb_id";
712 chatDesc.AHOnActive = "set";
713 chatDesc.AHOnActiveParams = "dblink=UI:SAVE:ISDETACHED:TELL|value=1";
714 chatDesc.AHOnDeactive = "set";
715 chatDesc.AHOnDeactiveParams = "dblink=UI:SAVE:ISDETACHED:TELL|value=0";
717 TellWindow = getChatWndMgr().createChatWindow(chatDesc);
718 if (!TellWindow) return;
719 TellWindow->setMenu("ui:interface:base_chat_box_menu"); */
722 //===========================================================================================================
723 void CPeopleInterraction::createTeamChat()
725 // create team chat (inserted in team people list)
726 CChatWindowDesc chatDesc
;
727 chatDesc
.FatherContainer
= "ui:interface";
728 chatDesc
.Title
= "uiTeamChatTitle";
729 chatDesc
.Listener
= &TeamChatEntryHandler
;
730 chatDesc
.Localize
= true;
731 chatDesc
.Savable
= true;
732 chatDesc
.Id
= "team_chat";
733 chatDesc
.AHOnCloseButton
= "proc";
734 chatDesc
.AHOnCloseButtonParams
= "team_chat_proc_close";
735 chatDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
737 TeamChat
= getChatWndMgr().createChatWindow(chatDesc
);
738 if (!TeamChat
) return;
739 TeamChat
->setMenu(STD_CHAT_SOURCE_MENU
);
742 //===========================================================================================================
743 void CPeopleInterraction::createGuildChat()
745 CChatWindowDesc chatDesc
;
746 chatDesc
.FatherContainer
= "ui:interface";
747 chatDesc
.Title
= "uiGuildChat";
748 chatDesc
.Listener
= &GuildChatEntryHandler
;
749 chatDesc
.Localize
= true;
750 chatDesc
.Savable
= true;
751 chatDesc
.Id
= "guild_chat";
752 chatDesc
.AHOnCloseButton
= "proc";
753 chatDesc
.AHOnCloseButtonParams
= "guild_chat_proc_close";
754 chatDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
756 GuildChat
= getChatWndMgr().createChatWindow(chatDesc
);
757 if (!GuildChat
) return;
758 GuildChat
->setMenu(STD_CHAT_SOURCE_MENU
);
761 //=================================================================================================================
762 void CPeopleInterraction::createDynamicChats()
764 for(uint i
=0;i
<CChatGroup::MaxDynChanPerPlayer
;i
++)
766 CChatWindowDesc chatDesc
;
767 chatDesc
.FatherContainer
= "ui:interface";
768 chatDesc
.Title
= toString("dummyDynChatTitle%d",i
); // title not used, but still important because create() test uniqueness
769 DynamicChatEntryHandler
[i
].DbIndex
= i
;
770 chatDesc
.Listener
= &DynamicChatEntryHandler
[i
];
771 chatDesc
.Localize
= false;
772 chatDesc
.Savable
= true;
773 chatDesc
.ChatTemplate
="dynamic_chat_id";
774 chatDesc
.ChatTemplateParams
.push_back(make_pair(string("dyn_chat_nb"),toString(i
)));
775 chatDesc
.Id
= string("dynamic_chat") + toString(i
);
776 // no active proc because active state is driven by database
777 chatDesc
.AHOnCloseButton
= "proc";
778 chatDesc
.AHOnCloseButtonParams
= string("dynamic_chat_proc_close|") + toString(i
);
779 chatDesc
.HeaderColor
= "UI:SAVE:WIN:COLORS:MEM";
781 DynamicChat
[i
] = getChatWndMgr().createChatWindow(chatDesc
);
782 if (!DynamicChat
[i
]) continue;
783 DynamicChat
[i
]->setMenu(STD_CHAT_SOURCE_MENU
);
788 //=================================================================================================================
789 void CPeopleInterraction::createTheUserChat()
791 CChatWindowDesc chatDesc
;
792 chatDesc
.FatherContainer
= "ui:interface";
793 chatDesc
.Title
= "uiUserChat";
794 chatDesc
.Listener
= NULL
;
795 chatDesc
.Localize
= true;
796 chatDesc
.Savable
= true;
797 chatDesc
.Id
= "user_chat";
798 chatDesc
.ChatTemplate
= "filtered_chat_id";
799 chatDesc
.AHOnActive
= "user_chat_active";
800 chatDesc
.AHOnCloseButton
= "set";
801 chatDesc
.AHOnCloseButtonParams
= "dblink=UI:SAVE:ISDETACHED:USER_CHAT|value=0";
803 TheUserChat
.Window
= getChatWndMgr().createChatWindow(chatDesc
);
804 if (!TheUserChat
.Window
) return;
805 TheUserChat
.Window
->getContainer()->setup();
806 // Configure filter for the new chat (by default, listen to everything but party chats)
807 TheUserChat
.Filter
.setTargetGroup(CChatGroup::say
);
808 // assoviate filter with chat window
809 TheUserChat
.Filter
.setChat(TheUserChat
.Window
);
813 class CHandlerUserChatActive
: public IActionHandler
815 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
817 CChatWindow
*pCGW
= dynamic_cast<CChatWindow
*>(PeopleInterraction
.TheUserChat
.Window
);
818 if (pCGW
== NULL
) return;
819 CCtrlTextButton
*pUserBut
= dynamic_cast<CCtrlTextButton
*>(pCGW
->getContainer()->getCtrl("content:target_button"));
820 CInterfaceGroup
*pEditBox
= dynamic_cast<CInterfaceGroup
*>(pCGW
->getContainer()->getGroup("content:ebw"));
825 CChatGroup::TGroupType m
= PeopleInterraction
.TheUserChat
.Filter
.getTargetGroup();
829 case CChatGroup::arround
:
830 case CChatGroup::say
: pUserBut
->setHardText("uiFilterAround"); break;
831 case CChatGroup::region
: pUserBut
->setHardText("uiFilterRegion"); break;
832 case CChatGroup::universe
: pUserBut
->setHardText("uiFilterUniverse"); break;
833 case CChatGroup::team
: pUserBut
->setHardText("uiFilterTeam"); break;
834 case CChatGroup::guild
: pUserBut
->setHardText("uiFilterGuild"); break;
836 pUserBut
->getParent()->updateCoords();
837 pUserBut
->updateCoords();
839 if (pEditBox
!= NULL
) pEditBox
->setW(-pUserBut
->getWReal()-4);
842 REGISTER_ACTION_HANDLER(CHandlerUserChatActive
, "user_chat_active");
844 //===========================================================================================================
845 void CPeopleInterraction::createChatGroup()
847 CChatWindowDesc chatDesc
;
848 chatDesc
.FatherContainer
= "ui:interface";
849 chatDesc
.Listener
= NULL
;
850 chatDesc
.Title
.clear(); // NB: the chatgroup is the only one that can be not named (because of uniqueness title test)
851 chatDesc
.Localize
= true;
852 chatDesc
.Savable
= true;
853 chatDesc
.ChatTemplate
= "main_chat_group";
854 chatDesc
.Id
= "main_chat";
855 chatDesc
.AHOnActive
= "proc";
856 chatDesc
.AHOnActiveParams
= "main_chat_group_active";
857 chatDesc
.AHOnDeactive
= "proc";
858 chatDesc
.AHOnDeactiveParams
= "main_chat_group_deactive";
860 ChatGroup
.Window
= getChatWndMgr().createChatGroupWindow(chatDesc
);
861 if (!ChatGroup
.Window
) return;
862 // Configure filter for the main chat. By default, it listen to everything (no party chats : none have been created yet)
863 ChatGroup
.Filter
.setTargetGroup(CChatGroup::say
);
864 // associate filter with chat window
865 ChatGroup
.Filter
.setChat(ChatGroup
.Window
);
868 class CHandlerChatGroupFilter
: public IActionHandler
870 void execute (CCtrlBase
*pCaller
, const std::string
&sParams
)
872 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
874 const string dynChatId
="dyn_chat";
876 bool writeRight
= true;
877 bool isDynChat
= false;
878 uint32 dynChatDbIndex
= 0;
881 CChatTargetFilter
&rCTF
= PeopleInterraction
.ChatGroup
.Filter
;
882 if (sParams
== "around") rCTF
.setTargetGroup(CChatGroup::say
);
883 else if (sParams
== "region") rCTF
.setTargetGroup(CChatGroup::region
);
884 else if (sParams
== "universe") rCTF
.setTargetGroup(CChatGroup::universe
);
885 else if (sParams
== "team") rCTF
.setTargetGroup(CChatGroup::team
);
886 else if (sParams
== "guild") rCTF
.setTargetGroup(CChatGroup::guild
);
887 else if (sParams
== "sysinfo")
889 rCTF
.setTargetGroup(CChatGroup::system
);
892 else if (sParams
.compare(0, dynChatId
.size(), dynChatId
)==0)
894 // get the number of this tab
896 fromString(sParams
.substr(dynChatId
.size()), dynChatDbIndex
);
897 dynChatDbIndex
= min(dynChatDbIndex
, (uint32
)(CChatGroup::MaxDynChanPerPlayer
-1));
898 rCTF
.setTargetGroup(CChatGroup::dyn_chat
, dynChatDbIndex
);
901 // inform DB for write right.
902 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MAIN_CHAT:WRITE_RIGHT")->setValue32(writeRight
);
903 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MAIN_CHAT:IS_DYN_CHAT")->setValue32(isDynChat
);
904 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MAIN_CHAT:INDEX_DYN_CHAT")->setValue32(dynChatDbIndex
);
907 // Update Chat Group Window from user chat button
909 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
911 CCtrlTextButton
*pUserBut
= dynamic_cast<CCtrlTextButton
*>(pCGW
->getContainer()->getCtrl("content:but_user"));
912 CCtrlTextButton
*pEmoteBut
= dynamic_cast<CCtrlTextButton
*>(pCGW
->getContainer()->getCtrl("content:but_emote"));
913 CInterfaceGroup
*pEditBox
= dynamic_cast<CInterfaceGroup
*>(pCGW
->getContainer()->getGroup("content:ebw"));
914 CInterfaceGroup
*pTextList
= dynamic_cast<CInterfaceGroup
*>(pCGW
->getContainer()->getGroup("content:cb"));
916 // Target button choose the right filter
919 // Special case of the user defined chat
920 if (sParams
== "user")
922 if (pUserBut
!= NULL
)
924 CChatGroup::TGroupType m
= PeopleInterraction
.TheUserChat
.Filter
.getTargetGroup();
928 case CChatGroup::arround
:
929 case CChatGroup::say
: pUserBut
->setHardText("uiFilterAround"); break;
930 case CChatGroup::region
: pUserBut
->setHardText("uiFilterRegion"); break;
931 case CChatGroup::team
: pUserBut
->setHardText("uiFilterTeam"); break;
932 case CChatGroup::guild
: pUserBut
->setHardText("uiFilterGuild"); break;
933 case CChatGroup::universe
: pUserBut
->setHardText("uiFilterUniverse"); break;
934 case CChatGroup::dyn_chat
:
935 uint32 index
= PeopleInterraction
.TheUserChat
.Filter
.getTargetDynamicChannelDbIndex();
936 uint32 textId
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:DYN_CHAT:CHANNEL"+toString(index
)+":NAME")->getValue32();
938 STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, title
);
941 // Dyn channel not available yet, so set to around
942 PeopleInterraction
.TheUserChat
.Filter
.setTargetGroup(CChatGroup::arround
);
943 pUserBut
->setHardText("uiFilterAround");
947 pUserBut
->setHardText(title
);
952 pUserBut
->setActive(true);
953 pUserBut
->getParent()->updateCoords();
954 pUserBut
->updateCoords();
956 pEmoteBut
->setActive (true);
957 pEmoteBut
->updateCoords ();
959 if (pEditBox
!= NULL
)
961 pEditBox
->setW(-pUserBut
->getWReal()-pEmoteBut
->getWReal()-8);
962 pEditBox
->setX(pUserBut
->getWReal()+4);
967 rCTF
.setTargetGroup(PeopleInterraction
.TheUserChat
.Filter
.getTargetGroup(), PeopleInterraction
.TheUserChat
.Filter
.getTargetDynamicChannelDbIndex());
971 if (pUserBut
!= NULL
) pUserBut
->setActive(false);
975 pEmoteBut
->setActive (true);
976 pEmoteBut
->updateCoords ();
979 if (pEditBox
!= NULL
)
982 pEditBox
->setW(-pEmoteBut
->getWReal()-4);
987 if (pTextList
!= NULL
) pTextList
->setX(0);
990 // if called from a tab button => force the tab ctrl button to have standard color
991 CCtrlTabButton
*pTabButton
= dynamic_cast<CCtrlTabButton
*>(pCaller
);
994 CRGBA stdColor
= CRGBA::stringToRGBA(CWidgetManager::getInstance()->getParser()->getDefine("chat_group_tab_color_normal").c_str());
995 pTabButton
->setTextColorNormal(stdColor
);
999 REGISTER_ACTION_HANDLER(CHandlerChatGroupFilter
, "chat_group_filter");
1002 //===========================================================================================================
1003 class CHandlerChatGroupUpdatePrompt
: public IActionHandler
1005 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
1007 // re set the target group will automatically reset the prompt and prompt color
1008 CChatTargetFilter
&rCTF
= PeopleInterraction
.ChatGroup
.Filter
;
1009 rCTF
.setTargetGroup(rCTF
.getTargetGroup(), rCTF
.getTargetDynamicChannelDbIndex());
1012 REGISTER_ACTION_HANDLER(CHandlerChatGroupUpdatePrompt
, "chat_group_update_prompt");
1015 //===========================================================================================================
1016 CPeopleList
*CPeopleInterraction::getPeopleListFromContainerID(const std::string
&id
)
1018 if (TeamList
.getContainerID() == id
) return &TeamList
;
1019 else if (FriendList
.getContainerID() == id
) return &FriendList
;
1020 else if (IgnoreList
.getContainerID() == id
) return &IgnoreList
;
1025 //===========================================================================================================
1026 bool CPeopleInterraction::getPeopleFromContainerID(const std::string
&id
, CPeopleList
*&peopleList
, uint
&destIndex
)
1029 // the name has the form "ui:interface:container_name_people_index"
1030 typedef std::string::size_type TCharPos
;
1031 TCharPos index
= id
.find_last_of("_");
1032 if (index
== std::string::npos
|| index
== 0) return false;
1033 TCharPos nextIndex
= id
.rfind(":", index
);
1034 if (nextIndex
== std::string::npos
) return false;
1035 std::string containerId
= id
.substr(nextIndex
+ 1, index
- nextIndex
- 1);
1036 // search a container with the good name
1037 CPeopleList
*pl
= getPeopleListFromContainerID(containerId
);
1038 if (!pl
) return false;
1040 sint peopleIndex
= pl
->getIndexFromContainerID(id
);
1041 if (peopleIndex
== -1) return false;
1043 destIndex
= (uint
) peopleIndex
;
1049 //===========================================================================================================
1050 bool CPeopleInterraction::getPeopleFromCurrentMenu(CPeopleList
*&peopleList
, uint
&index
)
1052 CInterfaceManager
*im
= CInterfaceManager::getInstance();
1053 // the group that launched the modal window (the menu) must be the header of the group container that represent a people entry
1054 CInterfaceGroup
*header
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getCtrlLaunchingModal());
1055 if (!header
) return false;
1056 // get the parent container
1057 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>(header
->getParent());
1058 if (!gc
) return false;
1059 return getPeopleFromContainerID(gc
->getId(), peopleList
, index
);
1062 //===========================================================================================================
1063 CPeopleList
*CPeopleInterraction::getPeopleListFromCurrentMenu()
1065 CInterfaceManager
*im
= CInterfaceManager::getInstance();
1066 // the group that launched the modal window (the menu) must be the header of the group container that represent a people entry
1067 CInterfaceGroup
*header
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getCtrlLaunchingModal());
1068 if (!header
) return NULL
;
1069 // get the parent container
1070 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>(header
->getParent());
1071 if (!gc
) return NULL
;
1072 std::string::size_type pos
= gc
->getId().find_last_of(":");
1073 if (pos
== std::string::npos
) return NULL
;
1074 return getPeopleListFromContainerID(gc
->getId().substr(pos
+ 1));
1077 //===========================================================================================================
1078 CFilteredChat
*CPeopleInterraction::getFilteredChatFromChatWindow(CChatWindow
*cw
)
1080 //if (cw == MainChat.Window) return &MainChat;
1081 if (cw
== ChatGroup
.Window
) return &ChatGroup
;
1082 if (cw
== AroundMe
.Window
) return &AroundMe
;
1083 if (cw
== TheUserChat
.Window
) return &TheUserChat
;
1084 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
1086 if (UserChat
[k
].Window
== cw
) return &UserChat
[k
];
1091 //===========================================================================================================
1092 void CPeopleInterraction::askAddContact(const string
&contactName
, CPeopleList
*pl
)
1097 if ((pl
!= &IgnoreList
) && (pl
!= &FriendList
))
1099 nlwarning("<askAddContact> For now, only support friend list & ignore list");
1103 // check that name isn't already in people list
1104 if (pl
->getIndexFromName(contactName
) != -1)
1106 // people already in list, can't add twice
1107 CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiContactAlreadyInList"));
1111 // add into server (NB: will be added by the server response later)
1112 const char *sMsg
= "TEAM:CONTACT_ADD";
1114 if(GenericMsgHeaderMngr
.pushNameToStream(sMsg
, out
))
1118 if (pl
== &IgnoreList
)
1121 if (pl
== &FriendList
)
1124 ucstring temp
= ucstring::makeFromUtf8(contactName
); // TODO: UTF-8 (serial)
1128 //nlinfo("impulseCallBack : %s %s %d sent", sMsg.c_str(), contactName.toString().c_str(), list);
1131 nlwarning("impulseCallBack : unknown message name : '%s'.", sMsg
);
1133 // NB: no client prediction, will be added by server later
1135 // Fake Local simulation
1136 if (ClientCfg
.Local
)
1138 sint index
= pl
->addPeople(contactName
);
1139 pl
->setOnline(index
, ccs_online
);
1140 updateAllFreeTellerHeaders();
1144 //=================================================================================================================
1145 void CPeopleInterraction::askMoveContact(uint peopleIndexInSrc
, CPeopleList
*plSRC
, CPeopleList
*plDST
)
1147 if ((plSRC
== NULL
) || (plDST
== NULL
)) return;
1148 if ((plSRC
!= &IgnoreList
) && (plSRC
!= &FriendList
))
1150 nlwarning("<askMoveContact> For now, only support friend list & ignore list");
1153 if ((plDST
!= &IgnoreList
) && (plDST
!= &FriendList
))
1155 nlwarning("<askMoveContact> For now, only support friend list & ignore list");
1158 if ( plDST
== plSRC
)
1160 // move from list to same => no op
1164 // check that index is already in people list
1165 if (peopleIndexInSrc
>= plSRC
->getNumPeople()) return;
1168 // Send message to server
1169 uint32 contactId
= plSRC
->getContactId(peopleIndexInSrc
);
1172 if (plSRC
== &FriendList
)
1175 if (plSRC
== &IgnoreList
)
1178 const std::string sMsg
= "TEAM:CONTACT_MOVE";
1180 if(GenericMsgHeaderMngr
.pushNameToStream(sMsg
, out
))
1182 out
.serial(contactId
);
1183 out
.serial(nListSRC
);
1185 //nlinfo("impulseCallBack : %s %d %d sent", sMsg.c_str(), contactId, nListSRC);
1188 nlwarning("impulseCallBack : unknown message name : '%s'.", sMsg
.c_str());
1190 // NB: no client prediction, will be added by server later
1192 // Fake Local simulation
1193 if (ClientCfg
.Local
)
1195 string peopleName
= plSRC
->getName(peopleIndexInSrc
);
1196 plSRC
->removePeople(peopleIndexInSrc
);
1197 sint dstIndex
= plDST
->addPeople(peopleName
);
1198 plDST
->setOnline(dstIndex
, ccs_online
);
1199 if (getChatGroupWindow())
1201 getChatGroupWindow()->updateAllFreeTellerHeaders();
1203 updateAllFreeTellerHeaders();
1207 //=================================================================================================================
1208 void CPeopleInterraction::askRemoveContact(uint peopleIndex
, CPeopleList
*pl
)
1210 if (pl
== NULL
) return;
1211 if ((pl
!= &IgnoreList
) && (pl
!= &FriendList
))
1213 nlwarning("<askRemoveContact> For now, only support friend pl & ignore pl");
1216 if (peopleIndex
>= pl
->getNumPeople())
1218 nlwarning("<askRemoveContact> bad index given");
1222 // send server message
1223 const std::string sMsg
= "TEAM:CONTACT_DEL";
1225 if(GenericMsgHeaderMngr
.pushNameToStream(sMsg
, out
))
1227 uint32 contactId
= pl
->getContactId(peopleIndex
);
1228 out
.serial(contactId
);
1230 if (pl
== &PeopleInterraction
.FriendList
)
1232 if (pl
== &PeopleInterraction
.IgnoreList
)
1236 //nlinfo("impulseCallBack : %s %d %d sent", sMsg.c_str(), contactId, nList);
1239 nlwarning("impulseCallBack : unknown message name : '%s'.", sMsg
.c_str());
1241 // NB: no client prediction, let the server delete the contact by message.
1243 // Fake Local simulation
1244 if (ClientCfg
.Local
)
1246 pl
->removePeople(peopleIndex
);
1247 updateAllFreeTellerHeaders();
1252 //=================================================================================================================
1253 void CPeopleInterraction::initContactLists( const std::vector
<uint32
> &vFriendListName
,
1254 const std::vector
<TCharConnectionState
> &vFriendListOnline
,
1255 const std::vector
<ucstring
> &vIgnoreListName
) // TODO: UTF-8 (serial)
1258 // clear the current lists if any
1259 FriendList
.removeAllPeoples();
1260 IgnoreList
.removeAllPeoples();
1262 // build the contact ids, like server did
1263 uint32 contactIdPool
= 0;
1264 for (uint i
= 0; i
< vFriendListName
.size(); ++i
)
1265 addContactInList(contactIdPool
++, vFriendListName
[i
], vFriendListOnline
[i
], 0);
1266 for (uint i
= 0; i
< vIgnoreListName
.size(); ++i
)
1267 addContactInList(contactIdPool
++, vIgnoreListName
[i
].toUtf8(), ccs_offline
, 1);
1268 updateAllFreeTellerHeaders();
1271 //=================================================================================================================
1272 void CPeopleInterraction::addContactInList(uint32 contactId
, const string
&nameIn
, TCharConnectionState online
, uint8 nList
)
1274 // select correct people list
1275 CPeopleList
&pl
= nList
==0?FriendList
:IgnoreList
;
1277 // remove the shard name if possible
1278 string name
= CEntityCL::removeShardFromName(nameIn
);
1280 // add the contact to this list
1281 sint index
= pl
.getIndexFromName(name
);
1282 // try to create if not found
1284 index
= pl
.addPeople(name
);
1288 pl
.setOnline(index
, online
);
1289 pl
.setContactId(index
, contactId
);
1292 CInterfaceManager
* pIM
= CInterfaceManager::getInstance();
1293 CPeopleList::TSortOrder order
= (CPeopleList::TSortOrder
)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
1294 FriendList
.sortEx(order
);
1297 //=================================================================================================================
1298 void CPeopleInterraction::addContactInList(uint32 contactId
, uint32 nameID
, TCharConnectionState online
, uint8 nList
)
1301 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
1302 if (pSMC
->getString(nameID
, name
))
1304 addContactInList(contactId
, name
, online
, nList
);
1305 // update free teller header
1306 updateAllFreeTellerHeaders();
1311 w
.ContactId
= contactId
;
1313 w
.List
= nList
; // Friend list == 0 // Ignore list == 1
1315 WaitingContacts
.push_back(w
);
1317 CInterfaceManager
* pIM
= CInterfaceManager::getInstance();
1318 CPeopleList::TSortOrder order
= (CPeopleList::TSortOrder
)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
1319 FriendList
.sortEx(order
);
1323 //=================================================================================================================
1324 bool CPeopleInterraction::isContactInList(const string
&nameIn
, uint8 nList
) const
1326 // select correct people list
1327 const CPeopleList
&pl
= nList
==0?FriendList
:IgnoreList
;
1328 // remove the shard name if possible
1329 string name
= CEntityCL::removeShardFromName(nameIn
);
1330 return pl
.getIndexFromName(name
) != -1;
1333 //=================================================================================================================
1334 void CPeopleInterraction::updateAllFreeTellerHeaders()
1336 CChatGroupWindow
*gcw
= getChatGroupWindow();
1339 gcw
->updateAllFreeTellerHeaders();
1343 //=================================================================================================================
1344 void CPeopleInterraction::removeAllFreeTellers()
1346 CChatGroupWindow
*gcw
= getChatGroupWindow();
1349 gcw
->removeAllFreeTellers();
1353 //=================================================================================================================
1354 void CPeopleInterraction::updateWaitingContacts()
1356 bool touched
= false;
1357 for (uint32 i
= 0; i
< WaitingContacts
.size();)
1359 SWaitingContact
&w
= WaitingContacts
[i
];
1361 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
1362 if (pSMC
->getString(w
.NameId
, name
))
1364 addContactInList(w
.ContactId
, name
, w
.Online
, w
.List
);
1365 WaitingContacts
.erase(WaitingContacts
.begin()+i
);
1375 updateAllFreeTellerHeaders();
1379 //=================================================================================================================
1380 void CPeopleInterraction::updateContactInList(uint32 contactId
, TCharConnectionState online
, uint nList
)
1384 sint index
= FriendList
.getIndexFromContactId(contactId
);
1387 // Only do work if online status has changed
1388 if (FriendList
.getOnline(index
) != online
)
1390 CCDBNodeLeaf
* node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_ONLINE_OFFLINE_NOTIFICATIONS_CB", false);
1391 if (node
&& node
->getValueBool())
1393 // Only show the message if this player is not in my guild (because then the guild manager will show a message)
1394 std::vector
<SGuildMember
> GuildMembers
= CGuildManager::getInstance()->getGuildMembers();
1395 bool bOnlyFriend
= true;
1396 string name
= toLower(FriendList
.getName(index
));
1397 for (uint i
= 0; i
< GuildMembers
.size(); ++i
)
1399 if (toLower(GuildMembers
[i
].Name
) == name
)
1401 bOnlyFriend
= false;
1406 TCharConnectionState prevState
= FriendList
.getOnline(index
);
1407 bool showMsg
= bOnlyFriend
&& (prevState
== ccs_offline
|| online
== ccs_offline
);
1409 // Player is not in my guild, and the status change is from offline to online/abroad online or vice versa.
1412 string msg
= (online
!= ccs_offline
) ? CI18N::get("uiPlayerOnline") : CI18N::get("uiPlayerOffline");
1413 strFindReplace(msg
, "%s", FriendList
.getName(index
));
1414 string cat
= getStringCategory(msg
, msg
);
1415 map
<string
, CClientConfig::SSysInfoParam
>::const_iterator it
;
1416 NLMISC::CRGBA col
= CRGBA::Yellow
;
1417 it
= ClientCfg
.SystemInfoParams
.find(toLowerAscii(cat
));
1418 if (it
!= ClientCfg
.SystemInfoParams
.end())
1420 col
= it
->second
.Color
;
1423 PeopleInterraction
.ChatInput
.AroundMe
.displayMessage(msg
, col
, 2, &dummy
);
1427 FriendList
.setOnline(index
, online
);
1433 sint index
= IgnoreList
.getIndexFromContactId(contactId
);
1435 IgnoreList
.setOnline(index
, online
);
1439 //=================================================================================================================
1440 void CPeopleInterraction::removeContactFromList(uint32 contactId
, uint8 nList
)
1444 sint index
= FriendList
.getIndexFromContactId(contactId
);
1446 FriendList
.removePeople(index
);
1450 sint index
= IgnoreList
.getIndexFromContactId(contactId
);
1452 IgnoreList
.removePeople(index
);
1454 updateAllFreeTellerHeaders();
1457 //=================================================================================================================
1458 bool CPeopleInterraction::testValidPartyChatName(const string
&title
)
1460 if (title
.empty()) return false;
1461 // shouldn't begin like 'user chat 1-5'
1462 const string
&userChatStr
= CI18N::get("uiUserChat");
1463 if (NLMISC::startsWith(title
, userChatStr
)) return false;
1464 // can't match a translation identifier
1465 if (CI18N::hasTranslation(title
)) return false;
1466 for(uint k
= 0; k
< PartyChats
.size(); ++k
) // there shouldn't be that much party chat simultaneously so a linear search is ok
1468 if (PartyChats
[k
].Window
->getTitle() == title
) return false;
1470 // check for other chat window names (local only ?)
1471 if (SystemInfo
&& title
== SystemInfo
->getTitle()) return false;
1472 if (AroundMe
.Window
&& title
== AroundMe
.Window
->getTitle()) return false;
1473 if (GuildChat
&& title
== GuildChat
->getTitle()) return false;
1474 if (TeamChat
&& title
== TeamChat
->getTitle()) return false;
1476 index
= FriendList
.getIndexFromName(title
);
1477 if (index
!= -1) return false;
1478 index
= IgnoreList
.getIndexFromName(title
);
1479 if (index
!= -1) return false;
1480 // TODO_GAMEDEV server test for the name (not only local), & modify callers of this function
1481 // The party chat should NOT have the name of a player
1482 // A player name is NOT valid if it is the same that a party chat name
1486 //=================================================================================================================
1487 bool CPeopleInterraction::removePartyChat(CChatWindow
*window
)
1489 if (!window
) return false;
1490 std::vector
<CPartyChatInfo
>::iterator it
;
1491 for(it
= PartyChats
.begin(); it
!= PartyChats
.end(); ++it
)
1493 if (it
->Window
== window
) break;
1495 if (it
!= PeopleInterraction
.PartyChats
.end())
1497 PeopleInterraction
.PartyChats
.erase(it
);
1498 getChatWndMgr().removeChatWindow(window
->getTitle());
1499 // TODO GAMEDEV : send msg to server to tell that the player has deleted this party chat.
1508 //=================================================================================================================
1509 void CPeopleInterraction::assignPartyChatMenu(CChatWindow
*partyChat
)
1511 if (!partyChat
) return;
1512 // TODO GAMEDEV : fill the 2 following boolean
1513 bool isTeamLeader
= true;
1514 bool isGuildLeader
= true;
1516 if (isTeamLeader
&& isGuildLeader
)
1518 partyChat
->setMenu("ui:interface:team_and_guild_chief_party_chat_menu");
1520 else if (isTeamLeader
)
1522 partyChat
->setMenu("ui:interface:team_chief_party_chat_menu");
1524 else if (isGuildLeader
)
1526 partyChat
->setMenu("ui:interface:guild_chief_party_chat_menu");
1530 //=================================================================================================================
1531 bool CPeopleInterraction::createNewPartyChat(const string
&title
)
1533 // now there are no party chat windows, party chat phrases must be filtered from the main chat
1535 // create a new party chat and set the focus on it
1536 CChatWindowDesc chatDesc
;
1537 //chatDesc.FatherContainer = "ui:interface:communication";
1538 chatDesc
.FatherContainer
= "ui:interface:contact_list";
1539 chatDesc
.Title
= title
;
1540 chatDesc
.Title
= title
;
1541 chatDesc
.Listener
= &PartyChatEntryHandler
;
1542 chatDesc
.Localize
= false;
1544 // CChatWindow *newPartyChat = getChatWndMgr().createChatWindow(chatDesc);
1545 CChatWindow
*newPartyChat
= NULL
;
1549 // popup the container
1551 newPartyChat->getContainer()->setup();
1552 newPartyChat->getContainer()->setOpen(true);
1553 newPartyChat->getContainer()->popupCurrentPos();
1554 newPartyChat->getContainer()->updateCoords();
1555 newPartyChat->getContainer()->center();
1556 newPartyChat->getContainer()->setX(newPartyChat->getContainer()->getX() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA));
1557 newPartyChat->getContainer()->setY(newPartyChat->getContainer()->getY() + (sint32) (rand() % PARTY_CHAT_SPAWN_DELTA));
1558 newPartyChat->getContainer()->enableBlink(2);
1562 pci
.Window
= newPartyChat
;
1563 pci
.ID
= PeopleInterraction
.CurrPartyChatID
++;
1564 pci
.Filter
= new CChatInputFilter
;
1565 pci
.Filter
->addListeningWindow(pci
.Window
);
1566 //CPeopleInterraction::assignPartyChatMenu(newPartyChat);
1567 PartyChats
.push_back(pci
);
1568 //newPartyChat->setKeyboardFocus();
1575 //=================================================================================================================
1576 void CPeopleInterraction::buildFilteredChatSummary(const CFilteredChat
&src
, CFilteredChatSummary
&fcs
)
1579 fcs
.SrcGuild
= ChatInput
.Guild
.isListeningWindow(src
.Window
);
1580 fcs
.SrcAroundMe
= ChatInput
.AroundMe
.isListeningWindow(src
.Window
);
1581 fcs
.SrcSystemInfo
= ChatInput
.SystemInfo
.isListeningWindow(src
.Window
);
1582 fcs
.SrcTeam
= ChatInput
.Team
.isListeningWindow(src
.Window
);
1583 fcs
.SrcTell
= ChatInput
.Tell
.isListeningWindow(src
.Window
);
1584 fcs
.SrcRegion
= ChatInput
.Region
.isListeningWindow(src
.Window
);
1585 fcs
.SrcUniverse
= ChatInput
.Universe
.isListeningWindow(src
.Window
);
1587 // fill target infos
1588 if (src
.Filter
.getTargetPartyChat() != NULL
|| !src
.Filter
.getTargetPlayer().empty())
1590 fcs
.Target
= CChatGroup::say
;
1594 fcs
.Target
= src
.Filter
.getTargetGroup();
1598 //=================================================================================================================
1599 void CPeopleInterraction::buildFilteredDynChatSummary(const CFilteredChat
&src
, CFilteredDynChatSummary
&fcs
)
1601 for (uint8 i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
1603 fcs
.SrcDynChat
[i
] = ChatInput
.DynamicChat
[i
].isListeningWindow(src
.Window
);
1607 //=================================================================================================================
1608 void CPeopleInterraction::saveFilteredChat(NLMISC::IStream
&f
, const CFilteredChat
&src
)
1611 if (src
.Window
== NULL
)
1620 CFilteredChatSummary fcs
;
1621 buildFilteredChatSummary(src
, fcs
);
1626 //=================================================================================================================
1627 void CPeopleInterraction::saveFilteredDynChat(NLMISC::IStream
&f
, const CFilteredChat
&src
)
1630 if (src
.Window
== NULL
)
1639 CFilteredDynChatSummary fcs
;
1640 buildFilteredDynChatSummary(src
, fcs
);
1645 //=================================================================================================================
1646 CChatGroupWindow
*CPeopleInterraction::getChatGroupWindow() const
1648 return dynamic_cast<CChatGroupWindow
*>(ChatGroup
.Window
);
1651 #define USER_CHATS_INFO_VERSION 2
1652 #define USER_DYN_CHATS_INFO_VERSION 1
1654 //=================================================================================================================
1655 bool CPeopleInterraction::saveUserChatsInfos(NLMISC::IStream
&f
)
1657 nlassert(!f
.isReading());
1660 sint ver
= f
.serialVersion(USER_CHATS_INFO_VERSION
);
1661 f
.serialCheck(NELID("TAHC"));
1662 //saveFilteredChat(f, MainChat);
1663 saveFilteredChat(f
, ChatGroup
);
1664 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
1666 saveFilteredChat(f
, UserChat
[k
]);
1668 f
.serialCheck(NELID("TAHC"));
1671 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
1672 sint32 index
= pCGW
? pCGW
->getTabIndex() : 0;
1674 saveFilteredChat(f
, TheUserChat
);
1676 // Save the free tellers only if they belongs to friend list to avoid the 'only growing' situation
1679 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
1682 pCGW
->saveFreeTeller(f
);
1686 catch(const NLMISC::EStream
&e
)
1688 nlwarning("Error while saving user chat infos : %s", e
.what());
1694 //=================================================================================================================
1695 bool CPeopleInterraction::saveUserDynChatsInfos(NLMISC::IStream
&f
)
1697 nlassert(!f
.isReading());
1700 sint ver
= f
.serialVersion(USER_DYN_CHATS_INFO_VERSION
);
1701 f
.serialCheck(NELID("OMGY"));
1704 saveFilteredDynChat(f
, TheUserChat
);
1707 catch(const NLMISC::EStream
&e
)
1709 nlwarning("Error while saving user dyn chat infos : %s", e
.what());
1715 //=================================================================================================================
1716 bool CPeopleInterraction::loadUserChatsInfos(NLMISC::IStream
&f
)
1718 removeAllUserChats();
1719 nlassert(f
.isReading());
1723 sint ver
= f
.serialVersion(USER_CHATS_INFO_VERSION
);
1724 f
.serialCheck(NELID("TAHC"));
1728 nlwarning("Bad data in user chats infos");
1731 CFilteredChatSummary fcs
;
1733 //setupUserChatFromSummary(fcs, MainChat);
1734 setupUserChatFromSummary(fcs
, ChatGroup
);
1736 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
1743 setupUserChatFromSummary(fcs
, UserChat
[k
]);
1746 f
.serialCheck(NELID("TAHC"));
1749 // CChatGroupWindow *pCGW = PeopleInterraction.getChatGroupWindow();
1752 /* Yoyo: decide to always start with the default channel (user) activated
1753 because complex (at this time, the buttons are not all active, must wait guild loading, UI:SAVE loading etc...)
1754 Hence this doesn't work for anything but User and Sysinfo (if it is activated....)
1755 NB: must still load the index for file format reason
1756 //if (pCGW) pCGW->setTabIndex(index);
1762 setupUserChatFromSummary(fcs
, TheUserChat
);
1765 // Load the free tellers
1768 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
1769 if (pCGW
) pCGW
->loadFreeTeller(f
);
1772 catch(const NLMISC::EStream
&e
)
1774 nlwarning("Error while loading user chat infos : %s", e
.what());
1780 //=================================================================================================================
1781 bool CPeopleInterraction::loadUserDynChatsInfos(NLMISC::IStream
&f
)
1783 nlassert(f
.isReading());
1787 sint ver
= f
.serialVersion(USER_DYN_CHATS_INFO_VERSION
);
1788 f
.serialCheck(NELID("OMGY"));
1792 nlwarning("Bad data in user dyn chats infos");
1795 CFilteredDynChatSummary fcs
;
1799 setupUserDynChatFromSummary(fcs
, TheUserChat
);
1802 catch(const NLMISC::EStream
&e
)
1804 nlwarning("Error while loading user dyn chat infos : %s", e
.what());
1811 //=================================================================================================================
1812 void CPeopleInterraction::setupUserChatFromSummary(const CFilteredChatSummary
&summary
, CFilteredChat
&dest
)
1814 // User Dest. Do not allow Universe Warning, because do not want a warning open at load (moreover, the UNIVERSE tab should not be activated)
1815 dest
.Filter
.setTargetGroup(summary
.Target
, 0, false);
1817 ChatInput
.AroundMe
.setWindowState(dest
.Window
, summary
.SrcAroundMe
);
1818 ChatInput
.Guild
.setWindowState(dest
.Window
, summary
.SrcGuild
);
1819 ChatInput
.SystemInfo
.setWindowState(dest
.Window
, summary
.SrcSystemInfo
);
1820 ChatInput
.Team
.setWindowState(dest
.Window
, summary
.SrcTeam
);
1821 ChatInput
.Tell
.setWindowState(dest
.Window
, summary
.SrcTell
);
1822 ChatInput
.Region
.setWindowState(dest
.Window
, summary
.SrcRegion
);
1823 ChatInput
.Universe
.setWindowState(dest
.Window
, summary
.SrcUniverse
);
1826 //=================================================================================================================
1827 void CPeopleInterraction::setupUserDynChatFromSummary(const CFilteredDynChatSummary
&summary
, CFilteredChat
&dest
)
1830 for (uint8 i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
1832 ChatInput
.DynamicChat
[i
].setWindowState(dest
.Window
, summary
.SrcDynChat
[i
]);
1836 //=================================================================================================================
1837 void CPeopleInterraction::removeAllUserChats()
1839 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
1841 if (UserChat
[k
].Window
)
1843 getChatWndMgr().removeChatWindow(UserChat
[k
].Window
);
1844 UserChat
[k
].Filter
.reset();
1845 UserChat
[k
].Window
= NULL
;
1850 //=================================================================================================================
1851 void CPeopleInterraction::createUserChat(uint index
)
1853 if (index
>= MaxNumUserChats
)
1855 nlwarning("Bad index");
1858 CChatWindowDesc chatDesc
;
1859 string userChatStr
= CI18N::get("uiUserChat");
1860 userChatStr
+= ' ' + toString(index
+ 1);
1861 //chatDesc.FatherContainer = "ui:interface:communication";
1862 chatDesc
.FatherContainer
= "ui:interface:contact_list";
1863 chatDesc
.Title
= userChatStr
;
1864 chatDesc
.Listener
= NULL
;
1865 chatDesc
.Localize
= false;
1866 chatDesc
.Savable
= true;
1867 chatDesc
.ChatTemplate
= "filtered_chat_id";
1868 UserChat
[index
].Window
= getChatWndMgr().createChatWindow(chatDesc
);
1869 if (!UserChat
[index
].Window
) return;
1870 UserChat
[index
].Window
->getContainer()->setup();
1871 // Configure filter for the new chat (by default, listen to everything but party chats)
1872 UserChat
[index
].Filter
.setTargetGroup(CChatGroup::say
);
1873 // assoviate filter with chat window
1874 UserChat
[index
].Filter
.setChat(UserChat
[index
].Window
);
1877 //=================================================================================================================
1878 void CPeopleInterraction::refreshActiveUserChats()
1880 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
1882 if (UserChat
[k
].Window
)
1884 UserChat
[k
].Window
->getContainer()->setActive(true);
1889 //=================================================================================================================
1890 void CPeopleInterraction::talkInDynamicChannel(uint32 channelNb
,string sentence
)
1892 if(channelNb
<CChatGroup::MaxDynChanPerPlayer
)
1894 DynamicChatEntryHandler
[channelNb
].msgEntered(sentence
,DynamicChat
[channelNb
]);
1898 //=================================================================================================================
1899 void CPeopleInterraction::displayTellInMainChat(const string
&playerName
)
1901 //CChatWindow *chat = PeopleInterraction.MainChat.Window;
1902 CChatWindow
*chat
= PeopleInterraction
.ChatGroup
.Window
;
1904 chat
->getContainer()->setActive (true);
1905 // make the container blink
1906 chat
->getContainer()->enableBlink(2);
1907 // TODO : center the view on the newly created container ?
1908 // display a new command '/name' in the chat. The player must enter a new unique name for the party chat.
1909 chat
->setCommand("tell " + playerName
+ " ", false);
1910 chat
->setKeyboardFocus();
1913 /////////////////////////////////////
1914 // ACTION HANDLERS FOR PEOPLE LIST //
1915 /////////////////////////////////////
1917 //=================================================================================================================
1918 // Target a member of the team
1919 // See also CAHTargetTeammateShortcut
1920 class CHandlerTeamTarget
: public IActionHandler
1922 void execute (CCtrlBase
* /* pCaller */, const std::string
&sParams
)
1924 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1926 // retrieve the index of the people
1927 uint peopleIndex
= 0;
1929 // If comes from the button, get direct index
1930 if( !sParams
.empty() )
1932 fromString(sParams
, peopleIndex
);
1935 // else comes from a menu.
1939 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
1941 if (list
== &PeopleInterraction
.TeamList
) // check for good list
1946 // If success to get the team index
1949 // Get the team name id.
1950 CLFECOMMON::TClientDataSetIndex entityId
= CLFECOMMON::INVALID_CLIENT_DATASET_INDEX
;
1951 CCDBNodeLeaf
*prop
= NLGUI::CDBManager::getInstance()->getDbProp(toString(TEAM_DB_PATH
":%d:UID", peopleIndex
), false);
1953 entityId
= prop
->getValue32();
1955 if(entityId
!= CLFECOMMON::INVALID_CLIENT_DATASET_INDEX
)
1957 // get the entity by its received name
1958 CEntityCL
*entity
= EntitiesMngr
.getEntityByCompressedIndex(entityId
);
1960 // Select this entity.
1961 UserEntity
->selection(entity
->slot());
1964 // the entity is not in vision, can't select it
1965 pIM
->displaySystemInfo(CI18N::get("uiTeamSelectNotInVision"), "CHK");
1971 REGISTER_ACTION_HANDLER( CHandlerTeamTarget
, "team_target" );
1973 //=================================================================================================================
1974 // Dismiss a member from the team
1975 class CHandlerDismissMember
: public IActionHandler
1978 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
1980 // retrieve the index of the people
1983 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
1985 if (list
== &PeopleInterraction
.TeamList
) // check for good list
1987 const string msgName
= "TEAM:KICK";
1989 if(GenericMsgHeaderMngr
.pushNameToStream(msgName
, out
))
1991 uint8 teamMember
= (uint8
) peopleIndex
;
1992 out
.serial(teamMember
);
1994 //nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember);
1997 nlwarning("command 'dismiss_member': unknown message named '%s'.", msgName
.c_str());
2002 REGISTER_ACTION_HANDLER( CHandlerDismissMember
, "dismiss_member");
2004 //=================================================================================================================
2005 // Set the leader of the team
2006 class CHandlerSetTeamLeader
: public IActionHandler
2009 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2011 // retrieve the index of the people
2014 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
2016 if (list
== &PeopleInterraction
.TeamList
) // check for good list
2019 const string msgName = "TEAM:SET_LEADER";
2021 if(GenericMsgHeaderMngr.pushNameToStream(msgName, out))
2023 uint8 teamMember = (uint8)(peopleIndex);
2024 out.serial(teamMember);
2026 //nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember);
2029 nlwarning("command 'set_leader': unknown message named '%s'.", msgName.c_str());
2031 NLMISC::ICommand::execute("a setTeamLeader " + toString(peopleIndex
), g_log
);
2036 REGISTER_ACTION_HANDLER( CHandlerSetTeamLeader
, "set_team_leader");
2038 //=================================================================================================================
2039 // Set a successor for the team
2040 class CHandlerSetSuccessor
: public IActionHandler
2043 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2045 // retrieve the index of the people
2048 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
2050 if (list
== &PeopleInterraction
.TeamList
) // check for good list
2052 if (ClientCfg
.Local
)
2054 NLGUI::CDBManager::getInstance()->getDbProp(TEAM_DB_PATH
":SUCCESSOR_INDEX")->setValue32(peopleIndex
);
2058 const string msgName
= "TEAM:SET_SUCCESSOR";
2060 if(GenericMsgHeaderMngr
.pushNameToStream(msgName
, out
))
2062 uint8 teamMember
= (uint8
) peopleIndex
;
2063 out
.serial(teamMember
);
2065 //nlinfo("impulseCallBack : %s %d sent", msgName.c_str(), teamMember);
2068 nlwarning("command 'set_successor': unknown message named '%s'.", msgName
.c_str());
2074 REGISTER_ACTION_HANDLER( CHandlerSetSuccessor
, "set_successor");
2077 //=================================================================================================================
2078 // player or leader quit the team
2079 class CHandlerQuitTeam
: public IActionHandler
2082 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2084 // Create the message for the server to execute a phrase.
2085 const string msgName
= "TEAM:LEAVE";
2087 if(GenericMsgHeaderMngr
.pushNameToStream(msgName
, out
))
2090 //nlinfo("impulseCallBack : %s sent", msgName.c_str());
2093 nlwarning("CHandlerContextQuitTeam::execute: unknown message name : '%s'.", msgName
.c_str());
2096 REGISTER_ACTION_HANDLER( CHandlerQuitTeam
, "quit_team");
2098 //=================================================================================================================
2099 // The leader enable / disbale seeds sharing
2100 class CHandlerShareSeeds
: public IActionHandler
2103 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2105 // TODO_GAMEDEV : enable disable seeds sharing
2108 REGISTER_ACTION_HANDLER( CHandlerShareSeeds
, "share_seeds");
2114 //=================================================================================================================
2115 // Remove a contact from a list
2116 class CHandlerRemoveContact
: public IActionHandler
2119 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2121 // retrieve the index of the people
2124 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
2126 PeopleInterraction
.askRemoveContact(peopleIndex
, list
);
2130 REGISTER_ACTION_HANDLER( CHandlerRemoveContact
, "remove_contact");
2132 //=================================================================================================================
2133 // Invoke the 'tell' command on a contact from its menu
2134 // The tell command is displayed in the 'around me' window
2135 class CHandlerMenuTellContact
: public IActionHandler
2138 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2140 // retrieve the index of the people
2143 if (PeopleInterraction
.getPeopleFromCurrentMenu(list
, peopleIndex
))
2145 CPeopleInterraction::displayTellInMainChat(list
->getName(peopleIndex
));
2149 REGISTER_ACTION_HANDLER( CHandlerMenuTellContact
, "menu_tell_contact");
2152 //=================================================================================================================
2153 // Invoke the 'tell' command on a contact from a left click
2154 class CHandlerTellContact
: public IActionHandler
2156 void execute (CCtrlBase
*pCaller
, const std::string
&/* sParams */)
2158 if (!pCaller
) return;
2159 CInterfaceGroup
*ig
= pCaller
->getParent();
2161 CGroupContainer
*gc
= static_cast< CGroupContainer
* >( ig
->getEnclosingContainer() );
2165 if (PeopleInterraction
.getPeopleFromContainerID(gc
->getId(), list
, peopleIndex
))
2167 CPeopleInterraction::displayTellInMainChat(list
->getName(peopleIndex
));
2172 REGISTER_ACTION_HANDLER( CHandlerTellContact
, "tell_contact");
2175 //=================================================================================================================
2176 std::string LastFatherAddContactId
;
2177 // Add a contact to the list, first step
2178 class CHandlerAddContactBegin
: public IActionHandler
2181 void execute (CCtrlBase
*pCaller
, const std::string
&sParams
)
2183 /** This msg may have been triggered from valid button or from the edit box itself, so retrieve
2184 * the edit box from the enclosing group
2186 // Get enclosing container to know in which people list we are
2190 CInterfaceGroup
*group
= pCaller
->getParent();
2194 group
= group
->getParent();
2197 LastFatherAddContactId
= group
->getId();
2198 if (!LastFatherAddContactId
.empty())
2200 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2201 string groupName
= getParam(sParams
, "group");
2202 CInterfaceGroup
*gc
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(groupName
));
2205 CGroupEditBox
*geb
= dynamic_cast<CGroupEditBox
*>(gc
->getGroup("add_contact_eb:eb"));
2206 geb
->setInputString(std::string());
2208 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller
, sParams
);
2215 REGISTER_ACTION_HANDLER( CHandlerAddContactBegin
, "add_contact_begin");
2218 //=================================================================================================================
2219 // Add a contact to the list
2220 class CHandlerAddContact
: public IActionHandler
2223 void execute (CCtrlBase
*pCaller
, const std::string
&/* sParams */)
2225 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2227 /** This msg may have been triggered from valid button or from the edit box itself, so retrieve
2228 * the edit box from the enclosing group
2230 // Get enclosing container to know in which people list we are
2231 if (!LastFatherAddContactId
.empty() && pCaller
)
2233 CInterfaceGroup
*fatherGC
= pCaller
->getParent();
2236 // Look for the root parent
2239 CInterfaceGroup
*parent
= fatherGC
->getParent();
2240 if (!parent
|| (parent
->getId()=="ui:interface"))
2245 // Get the modal edit box
2246 CGroupEditBox
*geb
= dynamic_cast<CGroupEditBox
*>(fatherGC
->getGroup("add_contact_eb:eb"));
2247 if (geb
&& !geb
->getInputString().empty())
2249 std::string::size_type lastIndex
= LastFatherAddContactId
.rfind(":");
2250 if (lastIndex
!= std::string::npos
)
2252 // Get the people list with the preselected container ID
2253 CPeopleList
*peopleList
= PeopleInterraction
.getPeopleListFromContainerID(LastFatherAddContactId
.substr(lastIndex
+1));
2256 // don't add if it is the player name
2257 if (!ClientCfg
.Local
&& (UserEntity
->getEntityName() == geb
->getInputString()))
2259 displayVisibleSystemMsg(CI18N::get("uiCantAddYourSelfInContactList"));
2263 PeopleInterraction
.askAddContact(geb
->getInputString(), peopleList
);
2264 geb
->setInputString(std::string());
2268 geb
->setInputString(std::string());
2272 CAHManager::getInstance()->runActionHandler("leave_modal", pCaller
, "");
2275 REGISTER_ACTION_HANDLER( CHandlerAddContact
, "add_contact");
2278 //=================================================================================================================
2279 class CHandlerMoveContact
: public IActionHandler
2282 void execute (CCtrlBase
* /* pCaller */, const std::string
&sParams
)
2284 // retrieve the index of the people
2285 CPeopleList
*srcList
;
2287 if (PeopleInterraction
.getPeopleFromCurrentMenu(srcList
, peopleIndex
))
2289 // get the destination list
2290 CPeopleList
*destList
;
2292 if (!fromString(getParam(sParams
, "list"), listIndex
))
2294 nlwarning("Bad list index");
2300 destList
= &PeopleInterraction
.IgnoreList
;
2303 destList
= &PeopleInterraction
.FriendList
;
2305 default: nlwarning("Bad list index"); return;
2308 PeopleInterraction
.askMoveContact(peopleIndex
, srcList
, destList
);
2312 REGISTER_ACTION_HANDLER( CHandlerMoveContact
, "move_contact");
2315 //=================================================================================================================
2316 class CHandlerSortContacts
: public IActionHandler
2319 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2321 CInterfaceManager
* pIM
= CInterfaceManager::getInstance();
2322 nlinfo("Load Order : %d", NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
2323 CPeopleList::TSortOrder order
= (CPeopleList::TSortOrder
)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
2325 order
= (CPeopleList::TSortOrder
)(order
+ 1);
2326 if (order
== CPeopleList::END_SORT_ORDER
)
2328 order
= CPeopleList::START_SORT_ORDER
;
2331 nlinfo("Save Order : %d", order
);
2332 NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->setValue32((sint32
)order
);
2333 CPeopleList
*pl
= PeopleInterraction
.getPeopleListFromCurrentMenu();
2338 REGISTER_ACTION_HANDLER( CHandlerSortContacts
, "sort_contacts");
2341 //=================================================================================================================
2342 // Directly chat with a friend (launch a container chat)
2343 class CHandlerContactDirectChat
: public IActionHandler
2346 void execute (CCtrlBase
*pCaller
, const std::string
&/* sParams */)
2348 if (pCaller
== NULL
)
2351 CInterfaceGroup
*fatherGC
= pCaller
->getParent();
2352 if (fatherGC
== NULL
)
2354 fatherGC
= fatherGC
->getParent();
2355 if (fatherGC
== NULL
)
2357 string str
= fatherGC
->getId().substr(0,fatherGC
->getId().rfind('_'));
2358 str
= str
.substr(str
.rfind(':')+1, str
.size());
2359 CPeopleList
*peopleList
= PeopleInterraction
.getPeopleListFromContainerID(str
);
2360 if (peopleList
== NULL
)
2363 sint index
= peopleList
->getIndexFromContainerID(fatherGC
->getId());
2367 peopleList
->openCloseChat(index
, true);
2370 REGISTER_ACTION_HANDLER( CHandlerContactDirectChat
, "contact_direct_chat");
2377 //=================================================================================================================
2378 /** Menu to create a new party chat
2380 class CHandlerNewPartyChat
: public IActionHandler
2383 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2385 nlwarning("Deactivated for now!");
2387 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2388 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(NEW_PARTY_CHAT_WINDOW
));
2390 CWidgetManager::getInstance()->setTopWindow(gc
);
2391 // Set the keyboard focus
2392 CGroupEditBox
*eb
= dynamic_cast<CGroupEditBox
*>(gc
->getGroup("eb"));
2395 CWidgetManager::getInstance()->setCaptureKeyboard(eb
);
2396 eb
->setInputString(std::string());
2399 if (gc
->getActive())
2404 gc
->setActive(true);
2409 REGISTER_ACTION_HANDLER( CHandlerNewPartyChat
, "new_party_chat");
2411 //=================================================================================================================
2412 /** The name of a party chat has been validated
2414 class CHandlerValidatePartyChatName
: public IActionHandler
2416 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2418 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2419 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(NEW_PARTY_CHAT_WINDOW
));
2421 CGroupEditBox
*eb
= dynamic_cast<CGroupEditBox
*>(gc
->getGroup("eb"));
2423 string title
= eb
->getInputString();
2425 // TODO GAMEDEV : create (or join ?) a new channel. Each channel (party chat) should have a unique name in the game
2426 // moreover, it should not have the name of another available chat window (for example, it shouldn't be named 'Around Me')
2427 // It shouldn't have the name of an existing player, either..
2428 // Maybe this last test can be done in local only
2430 if (!PeopleInterraction
.testValidPartyChatName(title
))
2432 displayVisibleSystemMsg(title
+ " : " + CI18N::get("uiInvalidPartyChatName"));
2436 // create the party chat
2437 PeopleInterraction
.createNewPartyChat(title
);
2441 REGISTER_ACTION_HANDLER(CHandlerValidatePartyChatName
, "validate_party_chat_name");
2444 //=================================================================================================================
2445 /** Menu to create a new party chat
2449 //=================================================================================================================
2450 /** Menu to remove a currenlty created party chat
2452 class CHandlerRemovePartyChat
: public IActionHandler
2454 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2456 CChatWindow
*chat
= getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal());
2457 if (chat
) PeopleInterraction
.removePartyChat(chat
);
2460 REGISTER_ACTION_HANDLER( CHandlerRemovePartyChat
, "remove_party_chat");
2462 //=================================================================================================================
2463 /** TEMP : just create an 'invite' command in the 'around me' edit box
2465 class CHandlerPartyChatInvite
: public IActionHandler
2467 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2469 CChatWindow
*am
= PeopleInterraction
.AroundMe
.Window
;
2471 CCtrlBase
*cb
= am
->getContainer();
2475 cb
= cb
->getParent();
2477 // make the container blink
2478 am
->getContainer()->enableBlink(2);
2479 // TODO : center the view on the newly created container ?
2480 // display a new command '/name' in the chat. The player must enter a new unique name for the party chat.
2481 am
->setCommand("invite ", false);
2482 am
->setKeyboardFocus();
2485 REGISTER_ACTION_HANDLER( CHandlerPartyChatInvite
, "party_chat_invite" );
2488 //=================================================================================================================
2489 /** Add all members of the team to the party chat
2491 class CHandlerAddAllTeamMembersToPartyChat
: public IActionHandler
2493 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2495 // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal());
2496 // TODO GAMEDEV : add all team members
2499 REGISTER_ACTION_HANDLER( CHandlerAddAllTeamMembersToPartyChat
, "add_all_team_members");
2501 //=================================================================================================================
2502 /** Remove all members of the team to the party chat
2504 class CHandlerRemoveAllTeamMembersToPartyChat
: public IActionHandler
2506 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2508 // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal());
2509 // TODO GAMEDEV : remove all team members
2512 REGISTER_ACTION_HANDLER( CHandlerRemoveAllTeamMembersToPartyChat
, "remove_all_team_members");
2514 //=================================================================================================================
2515 /** Add all members of the guild to the party chat
2517 class CHandlerAddAllGuildMembersToPartyChat
: public IActionHandler
2519 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2521 // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal());
2522 // TODO GAMEDEV : add all guild members
2525 REGISTER_ACTION_HANDLER( CHandlerAddAllGuildMembersToPartyChat
, "add_all_guild_members");
2527 //=================================================================================================================
2528 /** Remove all members of the team to the party chat
2530 class CHandlerRemoveAllGuildMembersToPartyChat
: public IActionHandler
2532 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2534 // CChatWindow *chat = getChatWndMgr().getChatWindowFromCaller(CWidgetManager::getInstance()->getCtrlLaunchingModal());
2535 // TODO_GAMEDEV : remove all guild members
2538 REGISTER_ACTION_HANDLER( CHandlerRemoveAllGuildMembersToPartyChat
, "remove_all_guild_members");
2540 /////////////////////////////////////////
2541 // ACTION HANDLERS FOR MAIN/USER CHATS //
2542 /////////////////////////////////////////
2544 //=================================================================================================================
2545 /** Select the target on a filtered chat window
2546 * This create a menu with the standard window (team, around me ...) + the party chat windows
2548 class CHandlerSelectChatTarget
: public IActionHandler
2551 void execute (CCtrlBase
*pCaller
, const std::string
&sParams
)
2553 CChatWindow
*cw
= getChatWndMgr().getChatWindowFromCaller(pCaller
);
2555 ChatWindowForFilter
= cw
;
2556 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2558 std::string menuName
= getParam(sParams
, "menu");
2559 std::string strPartyChats
= getParam(sParams
, "party_chats");
2560 bool partyChats
= true;
2561 if (!strPartyChats
.empty())
2563 partyChats
= nlstricmp("true", strPartyChats
.c_str()) == 0;
2566 CGroupMenu
*menu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId(menuName
));
2568 // remove all party chat from the previous list
2569 uint lastTargetSelectedIndex
= 0;
2570 for(uint k
= 0; k
< menu
->getNumLine();)
2572 if (nlstricmp("chat_target_selected", menu
->getActionHandler(k
)) == 0)
2574 lastTargetSelectedIndex
= k
;
2576 if (fromString(menu
->getActionHandlerParam(k
), dummy
))
2578 // this is a party chat, removes the entry
2579 menu
->deleteLine(k
);
2580 -- lastTargetSelectedIndex
;
2593 CPeopleInterraction
&pl
= PeopleInterraction
;
2594 // add names of the party chats
2595 uint insertionIndex
= lastTargetSelectedIndex
+ 1; // insert after standard options
2598 for(uint l
= 0; l
< pl
.PartyChats
.size(); ++l
)
2600 menu
->addLineAtIndex(insertionIndex
, pl
.PartyChats
[l
].Window
->getTitle(), "chat_target_selected", toString(pl
.PartyChats
[l
].ID
));
2605 // Case of user chat in grouped chat window
2606 if ((cw
== PeopleInterraction
.ChatGroup
.Window
) || (cw
= PeopleInterraction
.TheUserChat
.Window
))
2608 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2609 cw
= PeopleInterraction
.TheUserChat
.Window
;
2610 // CChatStdInput &ci = PeopleInterraction.ChatInput;
2611 CGroupMenu
*pMenu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:user_chat_target_menu"));
2612 CViewTextMenu
*pMenuAround
= dynamic_cast<CViewTextMenu
*>(pMenu
->getElement("ui:interface:user_chat_target_menu:around"));
2613 CViewTextMenu
*pMenuRegion
= dynamic_cast<CViewTextMenu
*>(pMenu
->getElement("ui:interface:user_chat_target_menu:region"));
2614 CViewTextMenu
*pMenuUniverse
= dynamic_cast<CViewTextMenu
*>(pMenu
->getElement("ui:interface:user_chat_target_menu:universe"));
2615 CViewTextMenu
*pMenuTeam
= dynamic_cast<CViewTextMenu
*>(pMenu
->getElement("ui:interface:user_chat_target_menu:team"));
2616 CViewTextMenu
*pMenuGuild
= dynamic_cast<CViewTextMenu
*>(pMenu
->getElement("ui:interface:user_chat_target_menu:guild"));
2617 const bool teamActive
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:GROUP:0:PRESENT")->getValueBool();
2618 const bool guildActive
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:GUILD:NAME")->getValueBool();
2619 if (pMenuAround
) pMenuAround
->setGrayed (false);
2620 if (pMenuRegion
) pMenuRegion
->setGrayed (false);
2621 if (pMenuUniverse
) pMenuUniverse
->setGrayed (false);
2622 if (pMenuTeam
) pMenuTeam
->setGrayed (!teamActive
);
2623 if (pMenuGuild
) pMenuGuild
->setGrayed (!guildActive
);
2625 // Remove existing dynamic chats
2626 while (pMenu
->getNumLine() > 5)
2628 pMenu
->deleteLine(pMenu
->getNumLine()-1);
2631 // Add dynamic chats
2632 uint insertion_index
= 0;
2633 for (uint i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
2635 string s
= toString(i
);
2636 uint32 textId
= ChatMngr
.getDynamicChannelNameFromDbIndex(i
);
2637 bool active
= (textId
!= 0);
2640 uint32 canWrite
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:DYN_CHAT:CHANNEL"+s
+":WRITE_RIGHT")->getValue32();
2644 STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, title
);
2646 // replace dynamic channel name and shortcut
2647 string res
= CI18N::get("uiFilterMenuDynamic");
2648 strFindReplace(res
, "%channel", title
);
2649 strFindReplace(res
, "%shortcut", s
);
2651 pMenu
->addLineAtIndex(5 + insertion_index
, res
, "chat_target_selected", "dyn"+s
, "dyn"+s
);
2658 // activate the menu
2659 CWidgetManager::getInstance()->enableModalWindow(pCaller
, menuName
);
2662 REGISTER_ACTION_HANDLER( CHandlerSelectChatTarget
, "select_chat_target");
2664 //=================================================================================================================
2665 /** A target has been selected for a filtered chat
2667 class CHandlerChatTargetSelected
: public IActionHandler
2669 void execute (CCtrlBase
* /* pCaller */, const std::string
&sParams
)
2671 // for now, manage a single filtered chat window
2672 CChatWindow
*cw
= ChatWindowForFilter
;
2674 ChatWindowForFilter
= NULL
;
2675 CFilteredChat
*fc
= PeopleInterraction
.getFilteredChatFromChatWindow(cw
);
2677 CChatTargetFilter
&cf
= fc
->Filter
;
2679 if (nlstricmp(sParams
, "team") == 0)
2681 cf
.setTargetGroup(CChatGroup::team
);
2684 else if (nlstricmp(sParams
, "guild") == 0)
2686 cf
.setTargetGroup(CChatGroup::guild
);
2689 else if (nlstricmp(sParams
, "say") == 0)
2691 cf
.setTargetGroup(CChatGroup::say
);
2694 else if (nlstricmp(sParams
, "shout") == 0)
2696 cf
.setTargetGroup(CChatGroup::shout
);
2699 else if (nlstricmp(sParams
, "region") == 0)
2701 cf
.setTargetGroup(CChatGroup::region
);
2704 else if (nlstricmp(sParams
, "universe") == 0)
2706 cf
.setTargetGroup(CChatGroup::universe
);
2710 for (uint i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
2712 if (nlstricmp(sParams
, "dyn"+toString("%d", i
)) == 0)
2714 cf
.setTargetGroup(CChatGroup::dyn_chat
, i
);
2719 // Case of user chat in grouped chat window
2720 if (cw
== PeopleInterraction
.ChatGroup
.Window
)
2722 PeopleInterraction
.TheUserChat
.Filter
.setTargetGroup(cf
.getTargetGroup(), cf
.getTargetDynamicChannelDbIndex());
2723 CAHManager::getInstance()->runActionHandler("chat_group_filter", NULL
, "user");
2725 if (cw
== PeopleInterraction
.TheUserChat
.Window
)
2727 PeopleInterraction
.TheUserChat
.Filter
.setTargetGroup(cf
.getTargetGroup(), cf
.getTargetDynamicChannelDbIndex());
2728 CAHManager::getInstance()->runActionHandler("user_chat_active", NULL
, "");
2731 // The target should be a party chat
2733 if (fromString(sParams
, partyChatID
))
2735 // search party chat in the list
2736 std::vector
<CPartyChatInfo
> &partyChats
= PeopleInterraction
.PartyChats
;
2737 for(uint k
= 0; k
< partyChats
.size(); ++k
)
2739 if (partyChats
[k
].ID
== (uint
) partyChatID
)
2741 cf
.setTargetPartyChat(partyChats
[k
].Window
);
2745 // The party chat has been deleted while the menu was displayed it seems.. -> no-op
2750 REGISTER_ACTION_HANDLER( CHandlerChatTargetSelected
, "chat_target_selected");
2753 //=================================================================================================================
2754 /** If no more in team, leave team chat mode
2756 class CHandlerLeaveTeamChat
: public IActionHandler
2758 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
2760 if( PeopleInterraction
.TheUserChat
.Filter
.getTargetGroup() == CChatGroup::team
)
2762 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2765 if( !NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:IS_TEAM_PRESENT")->getValueBool() )
2767 ChatMngr
.updateChatModeAndButton(CChatGroup::say
);
2773 REGISTER_ACTION_HANDLER( CHandlerLeaveTeamChat
, "leave_team_chat");
2779 /** Create checkbox for a menu.
2781 static CInterfaceGroup
*createMenuCheckBox(const std::string
&onclickL
, const std::string
¶msL
, bool checked
)
2783 pair
<string
, string
> params
[2];
2784 params
[0].first
= "onclick_l";
2785 params
[0].second
= onclickL
;
2786 params
[1].first
= "params_l";
2787 params
[1].second
= paramsL
;
2789 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2790 CInterfaceGroup
*ig
= CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_checkbox", "", params
, sizeof(params
) / sizeof(params
[0]));
2791 if (!ig
) return NULL
;
2792 CCtrlBaseButton
*cb
= dynamic_cast<CCtrlBaseButton
*>(ig
->getCtrl("b"));
2793 if (!cb
) return NULL
;
2794 cb
->setPushed(checked
);
2800 //=================================================================================================================
2801 /** Display a menu to select the source on a filtered chat
2803 class CHandlerSelectChatSource
: public IActionHandler
2805 void execute (CCtrlBase
*pCaller
, const std::string
&/* sParams */)
2807 static const char *FILTER_TOGGLE
= "chat_source_selected";
2808 CPeopleInterraction
&pi
= PeopleInterraction
;
2809 CChatWindow
*cw
= getChatWndMgr().getChatWindowFromCaller(pCaller
);
2811 ChatWindowForFilter
= cw
;
2812 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2815 // *** get the main_chat or user_chat menu
2816 CGroupMenu
*menu
= NULL
;
2817 bool addUserChatEntries
= false;
2818 // If the current window is the chat group
2819 if (cw
== pi
.ChatGroup
.Window
)
2821 // select main chat menu
2822 menu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId(MAIN_CHAT_SOURCE_MENU
));
2824 // Remove all unused dynamic channels and set the names
2825 for (uint i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
2827 string s
= toString(i
);
2828 CViewTextMenu
*pVTM
= dynamic_cast<CViewTextMenu
*>(CWidgetManager::getInstance()->getElementFromId(MAIN_CHAT_SOURCE_MENU
+":tab:dyn"+s
));
2831 uint32 textId
= ChatMngr
.getDynamicChannelNameFromDbIndex(i
);
2832 bool active
= (textId
!= 0);
2833 pVTM
->setActive(active
);
2837 STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, title
);
2838 pVTM
->setText("["+s
+"] " + title
);
2843 // Menu with Filters
2844 CChatGroupWindow
*pWin
= pi
.getChatGroupWindow();
2845 if (pWin
->getTabIndex() == 5) // (5 == user) -> complete menu
2847 // get the real user chat setup
2848 cw
= pi
.TheUserChat
.Window
;
2849 addUserChatEntries
= true;
2853 // Don't add user chat since the selected TAB is not the user chat
2854 addUserChatEntries
= false;
2859 // Menu with Filters
2860 if (cw
== pi
.TheUserChat
.Window
)
2862 // select user chat menu
2863 menu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId(USER_CHAT_SOURCE_MENU
));
2864 addUserChatEntries
= true;
2869 // This is neither the ChatGroup, nor the UserChat. Should not be here.
2870 // Just open the STD chat menu, and quit
2871 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:GC_POPUP")->setValue64(cw
->getContainer()->isPopuped() || cw
->getContainer()->getLayerSetup() == 0 ? 1 : 0);
2872 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:GC_HAS_HELP")->setValue64(!cw
->getContainer()->getHelpPage().empty());
2873 CWidgetManager::getInstance()->enableModalWindow(pCaller
, STD_CHAT_SOURCE_MENU
);
2880 // *** remove any previous entries
2881 for(uint k
= 0; k
< menu
->getNumLine();)
2883 if (nlstricmp(FILTER_TOGGLE
, menu
->getActionHandler(k
)) == 0)
2885 menu
->deleteLine(k
);
2894 // *** create new entries
2895 if(addUserChatEntries
)
2897 uint insertionIndex
= 0;
2899 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uiAroundMe"), FILTER_TOGGLE
, "am");
2901 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "am", pi
.ChatInput
.AroundMe
.isListeningWindow(cw
)));
2905 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uiREGION"), FILTER_TOGGLE
, "region");
2907 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "region", pi
.ChatInput
.Region
.isListeningWindow(cw
)));
2911 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uiUNIVERSE"), FILTER_TOGGLE
, "universe");
2913 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "universe", pi
.ChatInput
.Universe
.isListeningWindow(cw
)));
2917 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uiTeam"), FILTER_TOGGLE
, "team");
2919 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "team", pi
.ChatInput
.Team
.isListeningWindow(cw
)));
2923 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uimGuild"), FILTER_TOGGLE
, "guild");
2925 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "guild", pi
.ChatInput
.Guild
.isListeningWindow(cw
)));
2930 //menu->addLineAtIndex(insertionIndex, CI18N::get("uiTell"), FILTER_TOGGLE, "tell");
2932 //menu->setUserGroupLeft(insertionIndex, createMenuCheckBox(FILTER_TOGGLE, "tell", pi.ChatInput.Tell.isListeningWindow(cw)));
2933 //++ insertionIndex;
2936 menu
->addLineAtIndex(insertionIndex
, CI18N::get("uiSystemInfo"), FILTER_TOGGLE
, "si");
2938 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "si", pi
.ChatInput
.SystemInfo
.isListeningWindow(cw
)));
2942 std::vector
<CPartyChatInfo
> &pc
= pi
.PartyChats
;
2943 for(uint l
= 0; l
< pc
.size(); ++l
)
2945 if (pc
[l
].Filter
!= NULL
)
2947 menu
->addLineAtIndex(insertionIndex
, pc
[l
].Window
->getTitle(), FILTER_TOGGLE
, toString(pc
[l
].ID
));
2948 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, toString(pc
[l
].ID
), pc
[l
].Filter
->isListeningWindow(cw
)));
2953 // Add all existing dynamic channels and set the names
2954 for (uint8 i
= 0; i
< CChatGroup::MaxDynChanPerPlayer
; i
++)
2956 string s
= toString(i
);
2957 uint32 textId
= ChatMngr
.getDynamicChannelNameFromDbIndex(i
);
2958 bool active
= (textId
!= 0);
2962 STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, title
);
2963 menu
->addLineAtIndex(insertionIndex
, "["+s
+"] " + title
, FILTER_TOGGLE
, "dyn"+s
);
2964 menu
->setUserGroupLeft(insertionIndex
, createMenuCheckBox(FILTER_TOGGLE
, "dyn"+s
, pi
.ChatInput
.DynamicChat
[i
].isListeningWindow(cw
)));
2972 // *** active the menu
2973 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:GC_POPUP")->setValue64(cw
->getContainer()->isPopuped() || cw
->getContainer()->getLayerSetup() == 0 ? 1 : 0);
2974 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:GC_HAS_HELP")->setValue64(!cw
->getContainer()->getHelpPage().empty());
2975 CWidgetManager::getInstance()->enableModalWindow(pCaller
, menu
);
2978 REGISTER_ACTION_HANDLER(CHandlerSelectChatSource
, "select_chat_source");
2982 //=================================================================================================================
2983 /** A new source has been selected / unselected from a filtered chat
2985 class CHandlerChatSourceSelected
: public IActionHandler
2987 void execute (CCtrlBase
* /* pCaller */, const std::string
&sParams
)
2991 CChatWindow
*cw
= ChatWindowForFilter
;
2994 CChatStdInput
&ci
= PeopleInterraction
.ChatInput
;
2997 if (cw
== PeopleInterraction
.ChatGroup
.Window
)
2999 CChatGroupWindow
*pWin
= PeopleInterraction
.getChatGroupWindow();
3000 if (pWin
->getTabIndex() != 5) // (5 == user)
3001 return; // Nothing to select except if user chat
3003 cw
= PeopleInterraction
.TheUserChat
.Window
;
3007 /*CCtrlBaseButton *button = dynamic_cast<CCtrlBaseButton *>(pCaller);
3010 button->setPushed(!button->getPushed());
3013 if (nlstricmp(sParams
, "guild") == 0)
3015 if (ci
.Guild
.isListeningWindow(cw
)) ci
.Guild
.removeListeningWindow(cw
);
3016 else ci
.Guild
.addListeningWindow(cw
);
3020 if (nlstricmp(sParams
, "team") == 0)
3022 if (ci
.Team
.isListeningWindow(cw
)) ci
.Team
.removeListeningWindow(cw
);
3023 else ci
.Team
.addListeningWindow(cw
);
3027 if (nlstricmp(sParams
, "am") == 0)
3029 if (ci
.AroundMe
.isListeningWindow(cw
)) ci
.AroundMe
.removeListeningWindow(cw
);
3030 else ci
.AroundMe
.addListeningWindow(cw
);
3034 if (nlstricmp(sParams
, "region") == 0)
3036 if (ci
.Region
.isListeningWindow(cw
)) ci
.Region
.removeListeningWindow(cw
);
3037 else ci
.Region
.addListeningWindow(cw
);
3041 if (nlstricmp(sParams
, "universe") == 0)
3043 if (ci
.Universe
.isListeningWindow(cw
)) ci
.Universe
.removeListeningWindow(cw
);
3044 else ci
.Universe
.addListeningWindow(cw
);
3048 if (nlstricmp(sParams
, "tell") == 0)
3050 if (ci
.Tell
.isListeningWindow(cw
)) ci
.Tell
.removeListeningWindow(cw
);
3051 else ci
.Tell
.addListeningWindow(cw
);
3055 if (nlstricmp(sParams
, "si") == 0)
3057 if (ci
.SystemInfo
.isListeningWindow(cw
)) ci
.SystemInfo
.removeListeningWindow(cw
);
3058 else ci
.SystemInfo
.addListeningWindow(cw
);
3062 if (fromString(sParams
, partyChatID
))
3064 std::vector
<CPartyChatInfo
> &partyChats
= PeopleInterraction
.PartyChats
;
3065 for(uint k
= 0; k
< partyChats
.size(); ++k
)
3067 if (partyChats
[k
].ID
== (uint
) partyChatID
)
3069 if (partyChats
[k
].Filter
!= NULL
)
3071 if (partyChats
[k
].Filter
->isListeningWindow(cw
)) partyChats
[k
].Filter
->removeListeningWindow(partyChats
[k
].Window
);
3072 else partyChats
[k
].Filter
->addListeningWindow(cw
);
3077 else if (nlstricmp(sParams
.substr(0, 3), "dyn") == 0)
3080 fromString(sParams
.substr(3), i
);
3081 if (ci
.DynamicChat
[i
].isListeningWindow(cw
)) ci
.DynamicChat
[i
].removeListeningWindow(cw
);
3082 else ci
.DynamicChat
[i
].addListeningWindow(cw
);
3086 REGISTER_ACTION_HANDLER( CHandlerChatSourceSelected
, "chat_source_selected");
3089 // show / hide the edit/box of a chatbox
3090 class CHandlerToggleChatEBVis
: public IActionHandler
3092 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
3094 CCtrlBase
*clm
= CWidgetManager::getInstance()->getCtrlLaunchingModal();
3096 CInterfaceGroup
*ig
= clm
->getParent();
3099 if (ig
->isGroupContainer()) break;
3100 ig
= ig
->getParent();
3104 CGroupContainer
*gc
= static_cast<CGroupContainer
*>(ig
);
3105 CInterfaceGroup
*eb
= gc
->getGroup("ebw");
3108 eb
->setActive(!eb
->getActive());
3110 CCtrlBase
*tb
= gc
->getCtrl("target_button");
3113 tb
->setActive(!tb
->getActive());
3117 REGISTER_ACTION_HANDLER( CHandlerToggleChatEBVis
, "toggle_chat_eb_vis");
3119 // create a new user chat
3120 class CHandlerNewUserChat
: public IActionHandler
3122 void execute (CCtrlBase
* /* pCaller */, const std::string
&/* sParams */)
3124 CPeopleInterraction
&pi
= PeopleInterraction
;
3125 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
3127 if (pi
.UserChat
[k
].Window
== NULL
) // not used ?
3129 pi
.createUserChat(k
);
3130 // add to std listeners
3131 pi
.ChatInput
.registerListeningWindow(pi
.UserChat
[k
].Window
);
3132 CGroupContainer
*gc
= pi
.UserChat
[k
].Window
->getContainer();
3134 gc
->popupCurrentPos();
3137 // change pos by a random amount
3138 gc
->setX(gc
->getX() + rand() % 20 - 10);
3139 gc
->setY(gc
->getY() + rand() % 20 - 10);
3140 gc
->invalidateCoords();
3142 pi
.UserChat
[k
].Window
->setKeyboardFocus();
3146 nlwarning("Too much user chats created");
3149 REGISTER_ACTION_HANDLER(CHandlerNewUserChat
, "new_user_chat");
3151 class CHandlerRemoveUserChat
: public IActionHandler
3153 void execute (CCtrlBase
*pCaller
, const std::string
&/* sParams */)
3155 CPeopleInterraction
&pi
= PeopleInterraction
;
3156 CChatWindow
*cw
= getChatWndMgr().getChatWindowFromCaller(pCaller
);
3158 CFilteredChat
*fc
= pi
.getFilteredChatFromChatWindow(cw
);
3160 getChatWndMgr().removeChatWindow(fc
->Window
);
3165 REGISTER_ACTION_HANDLER(CHandlerRemoveUserChat
, "remove_user_chat");
3167 ////////////////////////////////////////////
3168 // COMMAND RELATED TO PEOPLE INTERRACTION //
3169 ////////////////////////////////////////////
3172 //-----------------------------------------------
3174 //-----------------------------------------------
3175 NLMISC_COMMAND(ignore
, "add or remove a player from the ignore list", "<player name>")
3177 // Check parameters.
3183 // NB: playernames cannot have special characters
3184 const string
&playerName
= args
[0];
3186 // add to the ignore list
3187 PeopleInterraction
.askAddContact(playerName
, &PeopleInterraction
.IgnoreList
);
3194 Yoyo: Party chat is not ended: DON'T LET THOSE COMMANDS AVAILABLE!
3195 they made the client crash (cf createNewPartyChat)...
3198 // create a new party chat with the given name
3199 NLMISC_COMMAND(party_chat, "Create a new party chat", "<party_chat_name>")
3201 if (args.size() != 1)
3203 displayVisibleSystemMsg(CI18N::get("uiPartyChatCmd"));
3206 CPeopleInterraction &pi = PeopleInterraction;
3207 string title = args[0];
3209 if (!pi.testValidPartyChatName(title))
3211 displayVisibleSystemMsg(CI18N::get("uiInvalidPartyChatName"));
3215 PeopleInterraction.createNewPartyChat(title);
3219 // Remove the party chat with the given name
3220 NLMISC_COMMAND(remove_party_chat, "Remove a party chat", "<party_chat_name>")
3222 if (args.size() != 1)
3224 displayVisibleSystemMsg(CI18N::get("uiRemovePartyChatCmd"));
3227 string title = ucstring(args[0]);
3228 CChatWindow *chat = getChatWndMgr().getChatWindow(title);
3231 displayVisibleSystemMsg(title + " : " + CI18N::get("uiBadPartyChatName"));
3234 if (!PeopleInterraction.removePartyChat(chat))
3236 displayVisibleSystemMsg(title + " : " + CI18N::get("uiCantRemovePartyChat"));
3243 // Join a party chat whose name is known
3244 NLMISC_COMMAND(add_to_party_chat, "Join the given party chat", "<party_chat_name>")
3246 if (args.size() != 1)
3248 displayVisibleSystemMsg(CI18N::get("uiAddPartyChatCmd"));
3251 // TODO GAMEDEV : join the party chat
3255 // Invite someone in a party chat
3256 NLMISC_COMMAND(invite, "Invite someone to a party chat", "<people_name> <party_chat_name>")
3258 if (args.size() != 2)
3260 displayVisibleSystemMsg(CI18N::get("uiInviteCmd"));
3263 // TODO GAMEDEV : Send invite message to the server
3264 // Check that the inviter has created the chat ?
3265 // The people being invited should receive a popup to announce that he is being invited
3271 // ***************************************************************************
3274 // log all current chats in the file log_playername.txt saved in save directory
3275 // ***************************************************************************
3276 NLMISC_COMMAND(chatLog
, "", "")
3278 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3280 if(args
.size() != 0)
3283 if (pIM
->getLogState())
3284 pIM
->displaySystemInfo(CI18N::get("uiLogTurnedOff"));
3286 pIM
->setLogState(!pIM
->getLogState());
3288 if (pIM
->getLogState())
3289 pIM
->displaySystemInfo(CI18N::get("uiLogTurnedOn"));
3291 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHATLOG_STATE", false);
3294 node
->setValue32(pIM
->getLogState() ? 1 : 0);
3301 /////////////////////////
3302 // INTERFACE FUNCTIONS //
3303 /////////////////////////
3304 static DECLARE_INTERFACE_USER_FCT(getNumUserChatLeft
)
3306 CPeopleInterraction
&pi
= PeopleInterraction
;
3308 for(uint k
= 0; k
< MaxNumUserChats
; ++k
)
3310 if (pi
.UserChat
[k
].Window
== NULL
) ++ left
;
3312 result
.setInteger(left
);
3315 REGISTER_INTERFACE_USER_FCT("getNumUserChatLeft", getNumUserChatLeft
)
3318 //////////////////////////////////////
3319 // STATIC FUNCTIONS IMPLEMENTATIONS //
3320 //////////////////////////////////////
3322 static void displayVisibleSystemMsg(const string
&msg
, const string
&cat
)
3324 CInterfaceManager
*im
= CInterfaceManager::getInstance();
3325 im
->displaySystemInfo(msg
, cat
);
3326 if (CChatWindow::getChatWindowLaunchingCommand())
3328 CChatWindow::getChatWindowLaunchingCommand()->displayMessage(msg
, im
->getSystemInfoColor(cat
), CChatGroup::system
, 0, 2);
3333 NLMISC_COMMAND(testSI
, "tmp", "tmp")
3335 PeopleInterraction
.ChatInput
.DebugInfo
.displayMessage("test", CRGBA::Red
);