1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2021 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 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/>.
29 #include "game_context_menu.h"
30 #include "interface_v3/interface_manager.h"
31 #include "nel/gui/ctrl_text_button.h"
32 #include "nel/gui/group_menu.h"
34 #include "interface_v3/bot_chat_manager.h"
35 #include "interface_v3/guild_manager.h"
36 #include "interface_v3/people_interraction.h"
37 #include "continent_manager.h"
38 #include "main_loop.h"
39 #include "interface_v3/inventory_manager.h"
40 #include "motion/user_controls.h"
41 #include "sheet_manager.h"
42 #include "connection.h"
44 #include "game_share/constants.h"
45 #include "game_share/properties.h"
46 #include "game_share/bot_chat_types.h"
47 #include "game_share/animal_type.h"
49 #include "r2/editor.h"
52 using namespace NLMISC
;
56 extern CContinentManager ContinentMngr
;
58 // filter available programs depending on R2 mode
59 static uint32
filterAvailablePrograms(uint32 src
)
61 return R2::getEditor().isDMing() ? 0 : src
;
64 // ***************************************************************************
65 CGameContextMenu::CGameContextMenu()
69 _MilkoAttackDisengage
= NULL
;
71 _AvailablePrograms
= NULL
;
72 _ServerTeamPresent
= NULL
;
73 for(uint i
=0;i
<NUM_MISSION_OPTIONS
;i
++)
74 _MissionOption
[i
]= NULL
;
76 _ServerInPvpChallenge
= NULL
;
79 _OutpostRightToBannish
= NULL
;
80 for(uint i
=0;i
<BOTCHATTYPE::MaxR2MissionEntryDatabase
;i
++)
81 _MissionRing
[i
]= NULL
;
85 // ***************************************************************************
86 void CGameContextMenu::init(const std::string
&srcMenuId
)
88 std::string menuId
= srcMenuId
.empty() ? std::string("game_context_menu") : srcMenuId
;
89 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
91 _GroupMenu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getWindowFromId ("ui:interface:" + menuId
+ ""));
92 _ContextVal
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:TARGET:CONTEXT_VAL", false);
94 if(_GroupMenu
== NULL
)
96 nlwarning(("gamecontextmenu:init: 'ui:interface:" + menuId
+ "' window does not exist.").c_str());
100 _GroupMilkoPad
= "ui:interface:milko_pad";
101 if(_GroupMilkoPad
!= NULL
)
103 _MilkoAttackDisengage
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MK_ATTACK", false);
104 _MilkoAttDisBut1
= "ui:interface:milko_pad:content:mode1:mode1_content:milko_actions:action5";
105 _MilkoAttDisBut2
= "ui:interface:milko_pad:content:mode2:action5";
109 nlwarning("gamecontextmenu:init: 'ui:interface:milko_pad' window does not exist.");
112 if(_ContextVal
== NULL
)
114 nlwarning("gamecontextmenu:init: 'SERVER:TARGET:CONTEXT_VAL' node does not exist.");
119 _AvailablePrograms
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:PROGRAMMES");
120 _ServerTeamPresent
= NLGUI::CDBManager::getInstance()->getDbProp(TEAM_DB_PATH
":0:PRESENT", false);
121 _ServerInDuel
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IN_DUEL", false);
122 _ServerInPvpChallenge
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IN_PVP_CHALLENGE", false);
123 _WebPageTitle
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:WEB_PAGE_TITLE", false);
124 _OutpostSheet
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:OUTPOST", false);
125 _OutpostRightToBannish
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:CHARACTER_INFO:PVP_OUTPOST:RIGHT_TO_BANISH", false);
129 _TextLootAction
= "ui:interface:" + menuId
+ ":loot_action";
130 _TextQuartering
= "ui:interface:" + menuId
+ ":quartering";
131 _TextAttack
= "ui:interface:" + menuId
+ ":attack";
132 _TextDuel
= "ui:interface:" + menuId
+ ":duel";
133 _TextUnDuel
= "ui:interface:" + menuId
+ ":unduel";
134 _TextPvpChallenge
= "ui:interface:" + menuId
+ ":pvp_challenge";
135 _TextUnPvpChallenge
= "ui:interface:" + menuId
+ ":unpvp_challenge";
136 _TextExchange
= "ui:interface:" + menuId
+ ":exchange";
137 _TextMount
= "ui:interface:" + menuId
+ ":mount";
138 _TextFreeLook
= "ui:interface:" + menuId
+ ":free_look";
139 _TextMove
= "ui:interface:" + menuId
+ ":move";
140 _TextStop
= "ui:interface:" + menuId
+ ":stop";
141 _TextDisengage
= "ui:interface:" + menuId
+ ":disengage";
142 _TextUnseat
= "ui:interface:" + menuId
+ ":unseat";
143 _TextInfo
= "ui:interface:" + menuId
+ ":info";
144 _TextFollow
= "ui:interface:" + menuId
+ ":follow";
145 _TextAssist
= "ui:interface:" + menuId
+ ":assist";
146 _TextInvit
= "ui:interface:" + menuId
+ ":invit";
147 _TextGuildInvit
= "ui:interface:" + menuId
+ ":guild_invit";
148 _TextQuitTeam
= "ui:interface:" + menuId
+ ":quit_team";
149 _TextAddToFriendList
= "ui:interface:" + menuId
+ ":add_to_friend_list";
150 _TextTalk
= "ui:interface:" + menuId
+ ":talk";
151 _TextInvisible
= "ui:interface:" + menuId
+ ":invisible";
152 _TextInvulnerable
= "ui:interface:" + menuId
+ ":invulnerable";
153 _TextGod
= "ui:interface:" + menuId
+ ":god";
156 // Mission DB and Text link
157 for(uint k
= 0; k
< NUM_MISSION_OPTIONS
; ++k
)
159 _MissionOption
[k
] = NLGUI::CDBManager::getInstance()->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSIONS_OPTIONS:%d:TITLE", (int) k
), false);
160 _TextMission
[k
] = toString(("ui:interface:" + menuId
+ ":mo%d").c_str(), (int) k
);
163 // Mission Ring DB and Text link
164 for(uint k
= 0; k
< BOTCHATTYPE::MaxR2MissionEntryDatabase
; ++k
)
166 _MissionRing
[k
]= NLGUI::CDBManager::getInstance()->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSION_RING:%d:TITLE", k
), false);
167 _TextMissionRing
[k
] = toString(("ui:interface:" + menuId
+ ":mr%d").c_str(), (int) k
);
173 _TextNews
= "ui:interface:" + menuId
+ ":news";
174 _TextNewsAgressive
= "ui:interface:" + menuId
+ ":news_aggressive";
175 _TextTradeItem
= "ui:interface:" + menuId
+ ":trade_item";
176 _TextTradeTeleport
= "ui:interface:" + menuId
+ ":trade_teleport";
177 _TextTradeFaction
= "ui:interface:" + menuId
+ ":trade_faction";
178 _TextTradeCosmetic
= "ui:interface:" + menuId
+ ":trade_cosmetic";
179 _TextTradeGuildOptions
= "ui:interface:" + menuId
+ ":trade_guild_options";
180 _TextTradeOutpostBuilding
= "ui:interface:" + menuId
+ ":trade_outpost_building";
181 _TextTradeGuildRoleMaster
= "ui:interface:" + menuId
+ ":trade_guild_role_master";
182 _TextTradePact
= "ui:interface:" + menuId
+ ":trade_pact";
183 _TextTradePhrase
= "ui:interface:" + menuId
+ ":trade_phrase";
184 _TextChooseMission
= "ui:interface:" + menuId
+ ":choose_mission";
185 _TextCreateGuild
= "ui:interface:" + menuId
+ ":create_guild";
186 _TextDynamicMission
= "ui:interface:" + menuId
+ ":dynamic_mission";
187 _TextChooseZCCharge
= "ui:interface:" + menuId
+ ":choose_zc_charge";
188 _TextChooseBuilding
= "ui:interface:" + menuId
+ ":choose_building";
189 _TextBuyRM
= "ui:interface:" + menuId
+ ":buy_rm";
190 _TextUpgradeRM
= "ui:interface:" + menuId
+ ":upgrade_rm";
191 _TextCancelZCCharge
= "ui:interface:" + menuId
+ ":cancel_zc_charge";
192 _TextDestroyBuilding
= "ui:interface:" + menuId
+ ":destroy_building";
193 _TextOutpostState
= "ui:interface:" + menuId
+ ":outpost_state";
194 _TextWebPage
= "ui:interface:" + menuId
+ ":web_page";
195 _TextOutpostBanishPlayer
= "ui:interface:" + menuId
+ ":outpost_bannish_player";
196 _TextOutpostBanishGuild
= "ui:interface:" + menuId
+ ":outpost_bannish_guild";
200 _TextPAFollow
= "ui:interface:" + menuId
+ ":pa_follow";
201 _TextPAStop
= "ui:interface:" + menuId
+ ":pa_stop";
202 _TextPAFree
= "ui:interface:" + menuId
+ ":pa_free";
203 _TextPAEnterStable
= "ui:interface:" + menuId
+ ":pa_enter_stable";
204 _TextPAEnterBag
= "ui:interface:" + menuId
+ ":pa_enter_bag";
207 _TextExtractRM
= "ui:interface:" + menuId
+ ":extract_rm";
210 _TextBuildTotem
= "ui:interface:" + menuId
+ ":build_totem";
214 // ***************************************************************************
216 bool ForceTalkWithBot
= false;
217 bool ForceTalkWithPlayer
= false;
219 // ***************************************************************************
220 void CGameContextMenu::update()
222 H_AUTO (RZ_Interface_updateContextMenu
)
224 if( !_ContextVal
|| !_GroupMenu
)
227 CProperties propValidation
= CProperties(_ContextVal
->getValue16());
230 uint32 availablePrograms
= filterAvailablePrograms((uint32
) _AvailablePrograms
->getValue32());
232 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
235 if ((_GroupMilkoPad
!= NULL
) && (_GroupMilkoPad
->getActive()))
239 _MilkoAttackDisengage
->setValue32(1);
240 if (_MilkoAttDisBut1
)
241 _MilkoAttDisBut1
->setHardText("uiMk_action5_1");
242 if (_MilkoAttDisBut2
)
243 _MilkoAttDisBut2
->setHardText("uiMk_action5_1");
247 _MilkoAttackDisengage
->setValue32(0);
248 if (_MilkoAttDisBut1
)
249 _MilkoAttDisBut1
->setHardText("uiMk_action5_0");
250 if (_MilkoAttDisBut2
)
251 _MilkoAttDisBut2
->setHardText("uiMk_action5_0");
255 // Is the menu active
256 if(!_GroupMenu
->getActive())
259 updateContextMenuMissionsOptions( UserEntity
->isRiding() );
261 updateContextMenuWebPage(availablePrograms
);
263 updateContextMenuOutpostState(availablePrograms
);
265 updateContextMenuOutpostBanish();
267 updateContextMenuMissionRing();
269 setupContextMenuCantTalk(); // can't talk by default
271 bool showGMOptions
= (hasPrivilegeDEV() || hasPrivilegeSGM() || hasPrivilegeGM() || hasPrivilegeVG() || hasPrivilegeSG() || hasPrivilegeEM() || hasPrivilegeEG() || hasPrivilegeOBSERVER() || hasPrivilegeTESTER());
274 _TextInvisible
->setActive(showGMOptions
);
276 if (_TextInvulnerable
)
277 _TextInvulnerable
->setActive(showGMOptions
);
280 _TextGod
->setActive(showGMOptions
);
283 // If mode Combat (no talk, no give, no mount, no extract_rm)
284 if(UserEntity
->isFighting())
288 _TextLootAction
->setActive(false);
291 _TextQuartering
->setActive(false);
292 // Disable talk, unless with a player
293 if (ForceTalkWithBot
) // tmp
295 updateContextMenuTalkEntries(availablePrograms
);
297 else if (ForceTalkWithPlayer
)
299 setupContextMenuTalkWithPlayer();
302 if(selection
&& selection
->Type
== CEntityCL::Player
)
304 setupContextMenuTalkWithPlayer();
309 _TextExchange
->setActive(false);
312 _TextMount
->setActive(false);
317 _TextFreeLook
->setActive(false);
320 _TextUnseat
->setActive(false);
321 // Disable extraction
323 _TextExtractRM
->setActive(false);
326 else if(UserEntity
->isRiding())
330 _TextLootAction
->setActive(false);
333 _TextQuartering
->setActive(false);
334 // No talk when riding
335 // No exchange when riding
337 _TextExchange
->setActive(false);
341 _TextMount
->setActive(false);
346 _TextFreeLook
->setActive(false);
349 _TextUnseat
->setActive(true);
350 // Disable extraction
352 _TextExtractRM
->setActive(false);
354 // Not in combat or riding mode.
360 _TextLootAction
->setActive(false);
361 // Action possible only if the client is not already busy and the selection is able to do this with you..
362 if(selection
&& selection
->isDead() && (selection
->properties().lootable() || selection
->properties().liftable())
363 && !R2::getEditor().isDMing()
365 _TextLootAction
->setActive(true);
370 _TextQuartering
->setActive(false);
371 // Action possible only if the client is not already busy and the selection is able to do this with you..
372 if(selection
&& selection
->isDead() && selection
->properties().harvestable() && !R2::getEditor().isDMing())
373 _TextQuartering
->setActive(true);
376 if (ForceTalkWithBot
) // tmp
378 updateContextMenuTalkEntries(availablePrograms
);
380 else if (ForceTalkWithPlayer
)
382 setupContextMenuTalkWithPlayer();
385 if(UserEntity
->selection() != UserEntity
->slot()) // Talking again to yourself ?
389 if (selection
->Type
== CEntityCL::Player
)
391 setupContextMenuTalkWithPlayer();
394 if(selection
->properties().talkableTo())
396 if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
398 // Can talk with bot if not too far
399 CVectorD vect1
= selection
->pos();
400 CVectorD vect2
= UserEntity
->pos();
401 double distanceSquare
= pow(vect1
.x
-vect2
.x
,2) + pow(vect1
.y
-vect2
.y
,2);
402 if (distanceSquare
<= MaxTalkingDistSquare
)
404 updateContextMenuTalkEntries(availablePrograms
);
406 // Special case for buildings
407 if (distanceSquare
<= MaxTalkingOutpostBuildingDistSquare
)
408 _OkTextTradeOutpostBuilding
= ((availablePrograms
& (1 << BOTCHATTYPE::TradeOutpostBuilding
)) != 0);
416 // Action possible only if the client is not already busy and the selection is able to do this with you..
417 if(selection
&& selection
->isPlayer() && selection
->properties().canExchangeItem())
418 _TextExchange
->setActive(!UserEntity
->isBusy());
420 _TextExchange
->setActive(false);
424 _TextFreeLook
->setActive(true);
427 _TextUnseat
->setActive(false);
428 // Enable extraction for a forage source
431 _TextExtractRM
->setActive(false);
432 if ( selection
&& selection
->isForageSource() )
433 _TextExtractRM
->setActive(true);
437 // Enable attack mode
439 _TextAttack
->setActive(canAttack());
442 // get current continent to check fame
443 string continent
= ContinentMngr
.cur()->SheetName
;
446 if (continent
== "lesfalaises.continent")
447 fameIndex
= CStaticFames::getInstance().getFactionIndex("matis");
448 else if (continent
== "fyros.continent")
449 fameIndex
= CStaticFames::getInstance().getFactionIndex("fyros");
450 else if (continent
== "tryker.continent")
451 fameIndex
= CStaticFames::getInstance().getFactionIndex("tryker");
452 else if (continent
== "lepaysmalade.continent")
453 fameIndex
= CStaticFames::getInstance().getFactionIndex("zorai");
456 if (fameIndex
!= CStaticFames::INVALID_FACTION_INDEX
)
458 CCDBNodeLeaf
*pLeafFame
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:FAME:PLAYER%d:VALUE", fameIndex
), false);
459 if (pLeafFame
!= NULL
)
460 fameValue
= pLeafFame
->getValue8();
464 bool enable_rumors
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:ENABLE_RUMORS")->getValueBool();
467 _TextNews
->setActive(enable_rumors
&& !UserEntity
->isFighting() && !UserEntity
->isRiding() && selection
&& !canAttack() && selection
->isNPC() && fameValue
>= -30);
469 if (_TextNewsAgressive
)
470 _TextNewsAgressive
->setActive(enable_rumors
&& !UserEntity
->isFighting() && !UserEntity
->isRiding() && selection
&& !canAttack() && selection
->isNPC() && fameValue
< -30);
473 if (_TextDuel
&& _TextUnDuel
)
475 if ((!UserEntity
->isRiding()) && (_ServerInDuel
->getValue8() != 0))
477 _TextDuel
->setActive(false);
478 _TextUnDuel
->setActive(true);
482 _TextDuel
->setActive(true);
483 _TextUnDuel
->setActive(false);
487 _TextDuel
->setActive(false);
488 _TextUnDuel
->setActive(false);
492 if (_TextPvpChallenge
&& _TextUnPvpChallenge
)
494 if ((!UserEntity
->isRiding()) && (_ServerInPvpChallenge
->getValue8() != 0))
496 _TextPvpChallenge
->setActive(false);
497 _TextUnPvpChallenge
->setActive(true);
499 else if (canPvpChallenge())
501 _TextPvpChallenge
->setActive(true);
502 _TextUnPvpChallenge
->setActive(false);
506 _TextPvpChallenge
->setActive(false);
507 _TextUnPvpChallenge
->setActive(false);
511 // Enable disengage mode
513 _TextDisengage
->setActive(canDisengage());
517 _TextMove
->setActive(!UserControls
.autowalkState());
518 // Enable Stop Autowalk
520 _TextStop
->setActive(UserControls
.autowalkState());
522 // Disable player properties
524 _TextInfo
->setActive(selection
&& (!selection
->isForageSource()));
529 // Action possible only if the client is not already busy and the selection is able to do this with you..
530 _TextFollow
->setActive(
532 (selection
->slot() != UserEntity
->slot()) &&
533 (!selection
->isForageSource()) &&
534 (selection
->isDead()==false) &&
535 (((availablePrograms
& (1 << BOTCHATTYPE::DontFollow
)) == 0)));
536 // See also below for mount/packer
542 // Action possible only if the client is not already busy and the selection is able to do this with you..
543 _TextAssist
->setActive(!R2::getEditor().isDMing() && selection
&& (selection
->slot() != UserEntity
->slot()) && (!selection
->isForageSource()) && (selection
->isDead()==false));
544 // See also below for mount/packer
550 bool invitable
= false;
551 // User should not be flagged as invitable by himself, so no need to check that selection is not the user
552 if(selection
&& selection
->isPlayer() && selection
->properties().invitable() && propValidation
.invitable() )
556 // Grey/Ungrey the entry.
557 _TextInvit
->setActive(invitable
);
564 if(filterAvailablePrograms(_AvailablePrograms
->getValue32())&(1 << BOTCHATTYPE::GuildInviteFlag
))
565 _TextGuildInvit
->setActive (true);
567 _TextGuildInvit
->setActive (false);
570 // Active "Quit Team" if you are a member of one.
573 if (_ServerTeamPresent
)
575 _TextQuitTeam
->setActive( _ServerTeamPresent
->getValueBool() );
579 // Invite to friend list (only if target is a player, and not a friend already)
580 if(_TextAddToFriendList
)
582 _TextAddToFriendList
->setActive(false);
583 if (selection
&& selection
->Type
== CEntityCL::Player
)
585 if (!selection
->getEntityName().empty())
587 sint peopleIndex
= PeopleInterraction
.FriendList
.getIndexFromName(selection
->getEntityName());
588 if (peopleIndex
== -1) // not already in friend list
590 _TextAddToFriendList
->setActive(true);
598 _TextMount
->setActive(false);
599 if(selection
&& (selection
->isUserPackAnimal() || (selection
->isUserMount())))
601 // Get the index of the selected animal, if owned by the player
603 if ( ! selection
->getPackAnimalIndexInDB( animalIndex
) )
606 // Disable 'Mount' if server says so
607 CViewTextMenu
*pTextMount
= NULL
;
608 if ( propValidation
.mountable() )
609 pTextMount
= _TextMount
;
611 _TextMount
->setActive( false ); // pTextMount remains NULL
613 // Enable/disable various menu items
614 bool ok
= testMenuOptionForPackAnimal( selection
, animalIndex
, true, _TextPAFollow
, _TextPAStop
, _TextPAFree
,
615 _TextPAEnterStable
, NULL
/*no 'leave stable' in context menu*/, pTextMount
,
616 NULL
/*unmount always active in context menu when the character is riding*/, _TextPAEnterBag
, NULL
);
618 // Follow & assist special case
620 _TextFollow
->setActive( false ); // can't follow own pet
622 _TextAssist
->setActive( false ); // can't assist a pet
624 // Write the selected pack animal, for future "beast_order" action handler
627 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
628 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:GCM_BEAST_SELECTED", false);
629 // beast_order AH start with 1 (0 for ALL beasts)
631 node
->setValue32(animalIndex
+1);
637 _TextPAFollow
->setActive(false);
639 _TextPAStop
->setActive(false);
640 if (_TextPAEnterStable
)
641 _TextPAEnterStable
->setActive(false);
643 _TextPAEnterBag
->setActive(false);
646 // Remove Free option to prevent miss click
648 _TextPAFree
->setActive(false);
654 _TextBuildTotem
->setActive(false);
655 if( availablePrograms
& ( 1 << BOTCHATTYPE::Totem
) )
657 _TextBuildTotem
->setActive(true);
661 // Apply real activation of Talk Texts.
666 // ***************************************************************************
667 bool CGameContextMenu::canAttack()
669 if (R2::getEditor().isDMing()) return false;
671 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
673 if (UserEntity
->isFighting() || UserEntity
->isRiding())
676 // To enter in combat, the user should not be talking.
677 if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
679 // If there is a selection.
680 if (selection
&& selection
->isDead() == false)
682 uint32 availablePrograms
= (uint32
) filterAvailablePrograms(_AvailablePrograms
->getValue32());
684 if(selection
->properties().attackable() || (availablePrograms
& (1<<BOTCHATTYPE::Attackable
)))
691 // ***************************************************************************
692 bool CGameContextMenu::canDuel()
694 if (UserEntity
->isFighting() || UserEntity
->isRiding())
697 // To enter in combat, the user should not be talking.
698 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
701 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
702 if (selection
== NULL
)
705 if (selection
->isPlayer())
706 if (selection
->isDead() == false)
712 // ***************************************************************************
713 bool CGameContextMenu::canPvpChallenge()
715 if (UserEntity
->isFighting() || UserEntity
->isRiding())
718 // To enter in combat, the user should not be talking.
719 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
722 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
723 if (selection
== NULL
)
726 if (selection
->isPlayer())
727 if (selection
->isDead() == false)
733 // ***************************************************************************
734 bool CGameContextMenu::canDisengage()
736 if (UserEntity
->isFighting())
742 // ***************************************************************************
743 bool CGameContextMenu::canTeamKick()
745 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
746 if (selection
!= NULL
)
748 sint n
= PeopleInterraction
.TeamList
.getIndexFromName(selection
->getEntityName());
755 // ***************************************************************************
756 void CGameContextMenu::updateContextMenuMissionsOptions( bool forceHide
)
758 for(uint k
= 0; k
< NUM_MISSION_OPTIONS
; ++k
)
760 CViewTextMenu
*pVTM
= _TextMission
[k
];
763 if ( _MissionOption
[k
] && (!forceHide
) )
765 uint32 textID
= (uint32
) _MissionOption
[k
]->getValue32();
769 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID
, result
);
772 result
= NLMISC::CI18N::get("uiMissionOptionNotReceived");
774 if (result
== string("Qui etes-vous ?")
775 || result
== string("Wer bist Du?")
776 || result
== string("Who are you?")
777 || result
== string("Quién eres tú?")
778 || result
== string("Кто ты?"))
780 pVTM
->setActive(false);
784 pVTM
->setText(result
);
785 pVTM
->setActive(true);
791 pVTM
->setActive(false);
797 pVTM
->setActive(false);
803 // ***************************************************************************
804 void CGameContextMenu::updateContextMenuWebPage(uint options
)
806 // Show the web page (title must be present)
807 _OkTextWebPage
= ((options
& (1 << BOTCHATTYPE::WebPageFlag
)) != 0);
809 _OkTextWebPage
= _WebPageTitle
&& _WebPageTitle
->getValue32()!=0;
811 // Change the WebPage text, when available
812 CViewTextMenu
*pVTM
= _TextWebPage
;
817 uint32 textID
= (uint32
) _WebPageTitle
->getValue32();
821 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID
, result
);
824 result
= NLMISC::CI18N::get("uiWebPageNameNotReceived");
826 pVTM
->setText(result
);
840 if (_TextWebPage
) _TextWebPage
->setActive(_OkTextWebPage
);
843 // ***************************************************************************
844 void CGameContextMenu::updateContextMenuOutpostState(uint options
)
846 CSheetId outpostSheet
;
849 _OkTextOutpostState
= false;
850 if ( (options
& (1 << BOTCHATTYPE::OutpostFlag
)) != 0 && _OutpostSheet
)
852 // check that the outpost sheet is correct
853 outpostSheet
= _OutpostSheet
->getValue32();
854 CEntitySheet
*s
= SheetMngr
.get(outpostSheet
);
855 if(s
&& s
->Type
== CEntitySheet::OUTPOST
)
856 _OkTextOutpostState
= true;
860 if(_OkTextOutpostState
)
862 CViewTextMenu
*pVTM
= _TextOutpostState
;
864 pVTM
->setText(STRING_MANAGER::CStringManagerClient::getOutpostLocalizedName(outpostSheet
));
868 if (_TextOutpostState
) _TextOutpostState
->setActive(_OkTextOutpostState
);
871 // ***************************************************************************
872 void CGameContextMenu::updateContextMenuOutpostBanish()
874 bool okForBanPlayer
= false;
875 bool okForBanGuild
= false;
877 // Test if the player can ban the targeted player / player's guild
878 extern void outpostTestUserCanBan(CCDBNodeLeaf
*dbBanRight
, bool &, bool &);
879 outpostTestUserCanBan(_OutpostRightToBannish
, okForBanPlayer
, okForBanGuild
);
882 if(_TextOutpostBanishPlayer
) _TextOutpostBanishPlayer
->setActive(okForBanPlayer
);
883 if(_TextOutpostBanishGuild
) _TextOutpostBanishGuild
->setActive(okForBanGuild
);
886 // ***************************************************************************
887 void CGameContextMenu::updateContextMenuMissionRing()
889 for(uint k
= 0; k
< BOTCHATTYPE::MaxR2MissionEntryDatabase
; ++k
)
891 CViewTextMenu
*pVTM
= _TextMissionRing
[k
];
895 if ( _MissionRing
[k
] )
896 textId
= _MissionRing
[k
]->getValue32();
897 // if the textId is ok and Flag is set.
901 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, result
);
904 result
= NLMISC::CI18N::get("uiMissionRingNameNotReceived");
906 pVTM
->setText(result
);
907 pVTM
->setActive(true);
912 pVTM
->setActive(false);
918 // ***************************************************************************
919 void CGameContextMenu::updateContextMenuTalkEntries(uint options
)
923 options
= std::numeric_limits
<uint
>::max(); // in local mode, force all options to be shown (for debug)
926 _OkTextNews
= true; //((options & (1 << BOTCHATTYPE::NewsFlag)));
928 _OkTextTradeItem
= ((options
& (1 << BOTCHATTYPE::TradeItemFlag
)) != 0);
929 _OkTextTradeTeleport
= ((options
& (1 << BOTCHATTYPE::TradeTeleportFlag
)) != 0);
930 _OkTextTradeFaction
= ((options
& (1 << BOTCHATTYPE::TradeFactionFlag
)) != 0);
931 _OkTextTradeCosmetic
= ((options
& (1 << BOTCHATTYPE::TradeCosmeticFlag
)) != 0);
932 _OkTextTradeGuildOptions
= ((options
& (1 << BOTCHATTYPE::TradeBuildingOptions
)) != 0);
933 _OkTextTradeOutpostBuilding
= ((options
& (1 << BOTCHATTYPE::TradeOutpostBuilding
)) != 0);
934 _OkTextTradeGuildRoleMaster
= ((options
& (1 << BOTCHATTYPE::GuildRoleMaster
)) != 0);
935 _OkTextTradePact
= ((options
& (1 << BOTCHATTYPE::TradePactFlag
)) != 0);
936 _OkTextTradePhrase
= ((options
& (1 << BOTCHATTYPE::TradePhraseFlag
)) != 0);
938 _OkTextChooseMission
= ((options
& (1 << BOTCHATTYPE::ChooseMissionFlag
)) != 0);
940 _OkTextCreateGuild
= ((options
& (1 << BOTCHATTYPE::CreateGuildFlag
)) != 0);
942 _OkTextChooseZCCharge
= ((options
& (1 << BOTCHATTYPE::AskGuildDutyFlag
)) != 0);
943 _OkTextCancelZCCharge
= ((options
& (1 << BOTCHATTYPE::CancelGuildDutyFlag
)) != 0);
945 /*_OkTextBuyRM= ((options & (1 << BOTCHATTYPE::)) != 0);
946 _OkTextUpgradeRM= ((options & (1 << BOTCHATTYPE::)) != 0);
947 _OkTextDestroyBuilding= ((options & (1 << BOTCHATTYPE::)) != 0);*/
948 // TODO BOTCHAT: RM Buy/Upgrade.
949 // TODO BOTCHAT: Declare war no more through "Mission Option"
950 // TODO BOTCHAT: Destroy Building only if already created
951 // TODO BOTCHAT: ZCBuilder is deprecated, as is _OkTextChooseBuilding
952 // TODO BOTCHAT: _OkTextDynamicMission is deprecated
953 _OkTextDynamicMission
= false;
955 _OkTextUpgradeRM
= false;
956 _OkTextChooseBuilding
= false;
957 _OkTextDestroyBuilding
= _OkTextChooseBuilding
;
961 // ***************************************************************************
962 void CGameContextMenu::setupContextMenuCantTalk()
964 updateContextMenuTalkEntries(0);
968 // ***************************************************************************
969 void CGameContextMenu::setupContextMenuTalkWithPlayer()
974 // ***************************************************************************
975 void CGameContextMenu::applyTextTalk()
977 if (_TextTradeItem
) _TextTradeItem
->setActive(_OkTextTradeItem
);
978 if (_TextTradeTeleport
) _TextTradeTeleport
->setActive(_OkTextTradeTeleport
);
979 if (_TextTradeFaction
) _TextTradeFaction
->setActive(_OkTextTradeFaction
);
980 if (_TextTradeCosmetic
) _TextTradeCosmetic
->setActive(_OkTextTradeCosmetic
);
981 if (_TextTradeGuildOptions
) _TextTradeGuildOptions
->setActive(_OkTextTradeGuildOptions
);
982 if (_TextTradeOutpostBuilding
) _TextTradeOutpostBuilding
->setActive(_OkTextTradeOutpostBuilding
);
983 if (_TextTradeGuildRoleMaster
) _TextTradeGuildRoleMaster
->setActive(_OkTextTradeGuildRoleMaster
);
984 if (_TextTradePact
) _TextTradePact
->setActive(_OkTextTradePact
);
985 if (_TextTradePhrase
) _TextTradePhrase
->setActive(_OkTextTradePhrase
);
986 if (_TextChooseMission
) _TextChooseMission
->setActive(_OkTextChooseMission
);
987 if (_TextCreateGuild
)
989 _TextCreateGuild
->setActive(_OkTextCreateGuild
);
990 // If the player is already in a guild set the text grayed
991 _TextCreateGuild
->setGrayed(CGuildManager::getInstance()->isInGuild());
994 if (_TextDynamicMission
) _TextDynamicMission
->setActive(_OkTextDynamicMission
);
995 if (_TextTalk
) _TextTalk
->setActive(_OkTextTalk
);
996 if (_TextChooseZCCharge
) _TextChooseZCCharge
->setActive(_OkTextChooseZCCharge
);
997 if (_TextChooseBuilding
) _TextChooseBuilding
->setActive(_OkTextChooseBuilding
);
998 if (_TextBuyRM
) _TextBuyRM
->setActive(_OkTextBuyRM
);
999 if (_TextUpgradeRM
) _TextUpgradeRM
->setActive(_OkTextUpgradeRM
);
1000 if (_TextCancelZCCharge
) _TextCancelZCCharge
->setActive(_OkTextCancelZCCharge
);
1001 if (_TextDestroyBuilding
) _TextDestroyBuilding
->setActive(_OkTextDestroyBuilding
);
1004 // ***************************************************************************
1007 * Enable/disable various menu items for animals.
1008 * selectedAnimalInVision can be NULL (out of vision)
1009 * index can be -1 (no owned animal)
1010 * Any CViewTextMenu* can be NULL
1012 bool testMenuOptionForPackAnimal( CEntityCL
* selectedAnimalInVision
, uint index
, bool clearAll
,
1013 CViewTextMenu
*pFollow
, CViewTextMenu
*pStop
, CViewTextMenu
*pFree
,
1014 CViewTextMenu
*pEnterStable
, CViewTextMenu
*pLeaveStable
,
1015 CViewTextMenu
*pMount
, CViewTextMenu
*pUnmount
,
1016 CViewTextMenu
*pEnterBag
, CViewTextMenu
*pLeaveBag
)
1020 // Disable and gray all by default
1021 if(pFollow
) { pFollow
->setActive(false); pFollow
->setGrayed(true); }
1022 if(pStop
) { pStop
->setActive(false); pStop
->setGrayed(true); }
1023 if(pFree
) { pFree
->setActive(false); pFree
->setGrayed(true); }
1024 if(pEnterStable
) { pEnterStable
->setActive(false); pEnterStable
->setGrayed(true); }
1025 if(pLeaveStable
) { pLeaveStable
->setActive(false); pLeaveStable
->setGrayed(true); }
1026 if(pEnterBag
) { pEnterBag
->setActive(false); pEnterBag
->setGrayed(true); }
1027 if(pLeaveBag
) { pLeaveBag
->setActive(false); pLeaveBag
->setGrayed(false); }
1028 if(pMount
) { pMount
->setActive(false); pMount
->setGrayed(true); }
1029 if(pUnmount
) { pUnmount
->setActive(false); pUnmount
->setGrayed(true); }
1032 // Don't enable anything if index not found (e.g. the character is not the owner of the animal)
1033 if ( (index
== (uint
)-1) || (!UserEntity
) )
1036 // Get animal status and type
1037 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1038 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS", index
), false);
1039 if(!node
) return false;
1040 ANIMAL_STATUS::EAnimalStatus status
= (ANIMAL_STATUS::EAnimalStatus
)node
->getValue32();
1041 node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:TYPE", index
), false);
1042 if(!node
) return false;
1043 ANIMAL_TYPE::EAnimalType anitype
= (ANIMAL_TYPE::EAnimalType
)node
->getValue32();
1045 if (anitype
!= ANIMAL_TYPE::Pet
)
1048 pEnterBag
->setActive(false);
1050 pLeaveBag
->setActive(false);
1053 // COMMON PART FOR ALL TYPES OF ANIMAL
1055 // Is the character mounted on the animal?
1056 bool userIsMountedOnIt
= false;
1057 if ( selectedAnimalInVision
&& (anitype
== ANIMAL_TYPE::Mount
) && UserEntity
->isRiding() )
1059 uint8 mountSlot
= (uint8
)IngameDbMngr
.getProp( "Entities:E" + toString(UserEntity
->slot()) + ":P" + toString(CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID
));
1060 userIsMountedOnIt
= (mountSlot
== selectedAnimalInVision
->slot());
1063 bool onLandscape
= ANIMAL_STATUS::isInLandscape(status
);
1064 double distanceSquare
= 0;
1065 if ( selectedAnimalInVision
)
1067 CVectorD vect1
= selectedAnimalInVision
->pos();
1068 CVectorD vect2
= UserEntity
->pos();
1069 distanceSquare
= pow(vect1
.x
-vect2
.x
,2) + pow(vect1
.y
-vect2
.y
,2);
1072 bool onBag
= ANIMAL_STATUS::isInBag(status
);
1074 // Enable option only if pack animal present
1075 if(ANIMAL_STATUS::isSpawned(status
))
1077 bool canEnterLeaveStable
= ANIMAL_STATUS::canEnterLeaveStable(status
);
1079 if (!userIsMountedOnIt
)
1081 if(pFollow
&& onLandscape
) pFollow
->setActive(true);
1082 if(pStop
&& onLandscape
) pStop
->setActive(true);
1084 // Enter/leave stable are only displayed when near a stable ('canEnterLeaveStable')
1085 if(pEnterStable
&& onLandscape
&& canEnterLeaveStable
) pEnterStable
->setActive(true);
1086 if(pLeaveStable
&& ANIMAL_STATUS::isInStable(status
) && canEnterLeaveStable
) pLeaveStable
->setActive(true);
1088 // Can always free, dead/alive, in or out stable animals
1091 pFree
->setActive(true);
1092 pFree
->setGrayed(false);
1096 // If alive (and close to the character), ungray all
1097 if(ANIMAL_STATUS::isAlive(status
))
1099 if (onLandscape
&& selectedAnimalInVision
&& (distanceSquare
<= MaxAnimalCommandDistSquare
))
1101 if(pFollow
) pFollow
->setGrayed(false);
1102 if(pStop
) pStop
->setGrayed(false);
1103 if(pEnterStable
) pEnterStable
->setGrayed(false);
1104 if (pEnterBag
&& !onBag
)
1105 pEnterBag
->setGrayed(false);
1107 if (pLeaveBag
&& onBag
)
1108 pLeaveBag
->setActive(true);
1110 if (pEnterBag
&& !onBag
&& anitype
== ANIMAL_TYPE::Pet
)
1111 pEnterBag
->setActive(true);
1113 if(pLeaveStable
) pLeaveStable
->setGrayed(false);
1117 // Specific part for mountable animal
1118 if ((anitype
== ANIMAL_TYPE::Mount
) &&
1119 (ANIMAL_STATUS::isSpawned(status
)) && onLandscape
)
1121 if ( userIsMountedOnIt
)
1123 // Always allow to unmount the mounted mount
1124 if(pUnmount
) pUnmount
->setActive(true);
1125 if(pUnmount
) pUnmount
->setGrayed(false);
1130 ((!selectedAnimalInVision
) || selectedAnimalInVision
->properties().mountable()))
1132 // Display 'Mount' if the entity is of mountable type
1133 pMount
->setActive(true);
1135 // Enable 'Mount' if the character is not busy and the entity is alive and close enough
1136 if(ANIMAL_STATUS::isAlive(status
) && (!UserEntity
->isRiding()) &&
1137 (!UserEntity
->isFighting()) && (!UserEntity
->isBusy()))
1139 if(selectedAnimalInVision
&& (distanceSquare
<= MaxAnimalCommandDistSquare
))
1141 pMount
->setGrayed(false);