1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 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 "main_loop.h"
38 #include "interface_v3/inventory_manager.h"
39 #include "motion/user_controls.h"
40 #include "sheet_manager.h"
42 #include "game_share/constants.h"
43 #include "game_share/properties.h"
44 #include "game_share/bot_chat_types.h"
45 #include "game_share/animal_type.h"
47 #include "r2/editor.h"
50 using namespace NLMISC
;
55 // filter available programs depending on R2 mode
56 static uint32
filterAvailablePrograms(uint32 src
)
58 return R2::getEditor().isDMing() ? 0 : src
;
61 // ***************************************************************************
62 CGameContextMenu::CGameContextMenu()
66 _MilkoAttackDisengage
= NULL
;
68 _AvailablePrograms
= NULL
;
69 _ServerTeamPresent
= NULL
;
70 for(uint i
=0;i
<NUM_MISSION_OPTIONS
;i
++)
71 _MissionOption
[i
]= NULL
;
73 _ServerInPvpChallenge
= NULL
;
76 _OutpostRightToBannish
= NULL
;
77 for(uint i
=0;i
<BOTCHATTYPE::MaxR2MissionEntryDatabase
;i
++)
78 _MissionRing
[i
]= NULL
;
82 // ***************************************************************************
83 void CGameContextMenu::init(const std::string
&srcMenuId
)
85 std::string menuId
= srcMenuId
.empty() ? std::string("game_context_menu") : srcMenuId
;
86 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
88 _GroupMenu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getWindowFromId ("ui:interface:" + menuId
+ ""));
89 _ContextVal
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:TARGET:CONTEXT_VAL", false);
91 if(_GroupMenu
== NULL
)
93 nlwarning(("gamecontextmenu:init: 'ui:interface:" + menuId
+ "' window does not exist.").c_str());
97 _GroupMilkoPad
= "ui:interface:milko_pad";
98 if(_GroupMilkoPad
!= NULL
)
100 _MilkoAttackDisengage
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MK_ATTACK", false);
101 _MilkoAttDisBut1
= "ui:interface:milko_pad:content:mode1:mode1_content:milko_actions:action5";
102 _MilkoAttDisBut2
= "ui:interface:milko_pad:content:mode2:action5";
106 nlwarning("gamecontextmenu:init: 'ui:interface:milko_pad' window does not exist.");
109 if(_ContextVal
== NULL
)
111 nlwarning("gamecontextmenu:init: 'SERVER:TARGET:CONTEXT_VAL' node does not exist.");
116 _AvailablePrograms
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:PROGRAMMES");
117 _ServerTeamPresent
= NLGUI::CDBManager::getInstance()->getDbProp(TEAM_DB_PATH
":0:PRESENT", false);
118 _ServerInDuel
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IN_DUEL", false);
119 _ServerInPvpChallenge
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:IN_PVP_CHALLENGE", false);
120 _WebPageTitle
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:WEB_PAGE_TITLE", false);
121 _OutpostSheet
= NLGUI::CDBManager::getInstance()->getDbProp("LOCAL:TARGET:CONTEXT_MENU:OUTPOST", false);
122 _OutpostRightToBannish
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:CHARACTER_INFO:PVP_OUTPOST:RIGHT_TO_BANISH", false);
126 _TextLootAction
= "ui:interface:" + menuId
+ ":loot_action";
127 _TextQuartering
= "ui:interface:" + menuId
+ ":quartering";
128 _TextAttack
= "ui:interface:" + menuId
+ ":attack";
129 _TextDuel
= "ui:interface:" + menuId
+ ":duel";
130 _TextUnDuel
= "ui:interface:" + menuId
+ ":unduel";
131 _TextPvpChallenge
= "ui:interface:" + menuId
+ ":pvp_challenge";
132 _TextUnPvpChallenge
= "ui:interface:" + menuId
+ ":unpvp_challenge";
133 _TextExchange
= "ui:interface:" + menuId
+ ":exchange";
134 _TextMount
= "ui:interface:" + menuId
+ ":mount";
135 _TextFreeLook
= "ui:interface:" + menuId
+ ":free_look";
136 _TextMove
= "ui:interface:" + menuId
+ ":move";
137 _TextStop
= "ui:interface:" + menuId
+ ":stop";
138 _TextDisengage
= "ui:interface:" + menuId
+ ":disengage";
139 _TextUnseat
= "ui:interface:" + menuId
+ ":unseat";
140 _TextInfo
= "ui:interface:" + menuId
+ ":info";
141 _TextFollow
= "ui:interface:" + menuId
+ ":follow";
142 _TextAssist
= "ui:interface:" + menuId
+ ":assist";
143 _TextInvit
= "ui:interface:" + menuId
+ ":invit";
144 _TextGuildInvit
= "ui:interface:" + menuId
+ ":guild_invit";
145 _TextQuitTeam
= "ui:interface:" + menuId
+ ":quit_team";
146 _TextAddToFriendList
= "ui:interface:" + menuId
+ ":add_to_friend_list";
147 _TextTalk
= "ui:interface:" + menuId
+ ":talk";
150 // Mission DB and Text link
151 for(uint k
= 0; k
< NUM_MISSION_OPTIONS
; ++k
)
153 _MissionOption
[k
] = NLGUI::CDBManager::getInstance()->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSIONS_OPTIONS:%d:TITLE", (int) k
), false);
154 _TextMission
[k
] = toString(("ui:interface:" + menuId
+ ":mo%d").c_str(), (int) k
);
157 // Mission Ring DB and Text link
158 for(uint k
= 0; k
< BOTCHATTYPE::MaxR2MissionEntryDatabase
; ++k
)
160 _MissionRing
[k
]= NLGUI::CDBManager::getInstance()->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSION_RING:%d:TITLE", k
), false);
161 _TextMissionRing
[k
] = toString(("ui:interface:" + menuId
+ ":mr%d").c_str(), (int) k
);
167 _TextNews
= "ui:interface:" + menuId
+ ":news";
168 _TextTradeItem
= "ui:interface:" + menuId
+ ":trade_item";
169 _TextTradeTeleport
= "ui:interface:" + menuId
+ ":trade_teleport";
170 _TextTradeFaction
= "ui:interface:" + menuId
+ ":trade_faction";
171 _TextTradeCosmetic
= "ui:interface:" + menuId
+ ":trade_cosmetic";
172 _TextTradeGuildOptions
= "ui:interface:" + menuId
+ ":trade_guild_options";
173 _TextTradeOutpostBuilding
= "ui:interface:" + menuId
+ ":trade_outpost_building";
174 _TextTradeGuildRoleMaster
= "ui:interface:" + menuId
+ ":trade_guild_role_master";
175 _TextTradePact
= "ui:interface:" + menuId
+ ":trade_pact";
176 _TextTradePhrase
= "ui:interface:" + menuId
+ ":trade_phrase";
177 _TextChooseMission
= "ui:interface:" + menuId
+ ":choose_mission";
178 _TextCreateGuild
= "ui:interface:" + menuId
+ ":create_guild";
179 _TextDynamicMission
= "ui:interface:" + menuId
+ ":dynamic_mission";
180 _TextChooseZCCharge
= "ui:interface:" + menuId
+ ":choose_zc_charge";
181 _TextChooseBuilding
= "ui:interface:" + menuId
+ ":choose_building";
182 _TextBuyRM
= "ui:interface:" + menuId
+ ":buy_rm";
183 _TextUpgradeRM
= "ui:interface:" + menuId
+ ":upgrade_rm";
184 _TextCancelZCCharge
= "ui:interface:" + menuId
+ ":cancel_zc_charge";
185 _TextDestroyBuilding
= "ui:interface:" + menuId
+ ":destroy_building";
186 _TextOutpostState
= "ui:interface:" + menuId
+ ":outpost_state";
187 _TextWebPage
= "ui:interface:" + menuId
+ ":web_page";
188 _TextOutpostBanishPlayer
= "ui:interface:" + menuId
+ ":outpost_bannish_player";
189 _TextOutpostBanishGuild
= "ui:interface:" + menuId
+ ":outpost_bannish_guild";
193 _TextPAFollow
= "ui:interface:" + menuId
+ ":pa_follow";
194 _TextPAStop
= "ui:interface:" + menuId
+ ":pa_stop";
195 _TextPAFree
= "ui:interface:" + menuId
+ ":pa_free";
196 _TextPAEnterStable
= "ui:interface:" + menuId
+ ":pa_enter_stable";
197 _TextPAEnterBag
= "ui:interface:" + menuId
+ ":pa_enter_bag";
200 _TextExtractRM
= "ui:interface:" + menuId
+ ":extract_rm";
203 _TextBuildTotem
= "ui:interface:" + menuId
+ ":build_totem";
207 // ***************************************************************************
209 bool ForceTalkWithBot
= false;
210 bool ForceTalkWithPlayer
= false;
212 // ***************************************************************************
213 void CGameContextMenu::update()
215 H_AUTO (RZ_Interface_updateContextMenu
)
217 if( !_ContextVal
|| !_GroupMenu
)
220 CProperties propValidation
= CProperties(_ContextVal
->getValue16());
223 uint32 availablePrograms
= filterAvailablePrograms((uint32
) _AvailablePrograms
->getValue32());
225 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
228 if ((_GroupMilkoPad
!= NULL
) && (_GroupMilkoPad
->getActive()))
232 _MilkoAttackDisengage
->setValue32(1);
233 if (_MilkoAttDisBut1
)
234 _MilkoAttDisBut1
->setHardText("uiMk_action5_1");
235 if (_MilkoAttDisBut2
)
236 _MilkoAttDisBut2
->setHardText("uiMk_action5_1");
240 _MilkoAttackDisengage
->setValue32(0);
241 if (_MilkoAttDisBut1
)
242 _MilkoAttDisBut1
->setHardText("uiMk_action5_0");
243 if (_MilkoAttDisBut2
)
244 _MilkoAttDisBut2
->setHardText("uiMk_action5_0");
248 // Is the menu active
249 if(!_GroupMenu
->getActive())
252 updateContextMenuMissionsOptions( UserEntity
->isRiding() );
254 updateContextMenuWebPage(availablePrograms
);
256 updateContextMenuOutpostState(availablePrograms
);
258 updateContextMenuOutpostBanish();
260 updateContextMenuMissionRing();
262 setupContextMenuCantTalk(); // can't talk by default
264 // If mode Combat (no talk, no give, no mount, no extract_rm)
265 if(UserEntity
->isFighting())
269 _TextLootAction
->setActive(false);
272 _TextQuartering
->setActive(false);
273 // Disable talk, unless with a player
274 if (ForceTalkWithBot
) // tmp
276 updateContextMenuTalkEntries(availablePrograms
);
278 else if (ForceTalkWithPlayer
)
280 setupContextMenuTalkWithPlayer();
283 if(selection
&& selection
->Type
== CEntityCL::Player
)
285 setupContextMenuTalkWithPlayer();
290 _TextExchange
->setActive(false);
293 _TextMount
->setActive(false);
298 _TextFreeLook
->setActive(false);
301 _TextUnseat
->setActive(false);
302 // Disable extraction
304 _TextExtractRM
->setActive(false);
307 else if(UserEntity
->isRiding())
311 _TextLootAction
->setActive(false);
314 _TextQuartering
->setActive(false);
315 // No talk when riding
316 // No exchange when riding
318 _TextExchange
->setActive(false);
322 _TextMount
->setActive(false);
327 _TextFreeLook
->setActive(false);
330 _TextUnseat
->setActive(true);
331 // Disable extraction
333 _TextExtractRM
->setActive(false);
335 // Not in combat or riding mode.
341 _TextLootAction
->setActive(false);
342 // Action possible only if the client is not already busy and the selection is able to do this with you..
343 if(selection
&& selection
->isDead() && (selection
->properties().lootable() || selection
->properties().liftable())
344 && !R2::getEditor().isDMing()
346 _TextLootAction
->setActive(true);
351 _TextQuartering
->setActive(false);
352 // Action possible only if the client is not already busy and the selection is able to do this with you..
353 if(selection
&& selection
->isDead() && selection
->properties().harvestable() && !R2::getEditor().isDMing())
354 _TextQuartering
->setActive(true);
357 if (ForceTalkWithBot
) // tmp
359 updateContextMenuTalkEntries(availablePrograms
);
361 else if (ForceTalkWithPlayer
)
363 setupContextMenuTalkWithPlayer();
366 if(UserEntity
->selection() != UserEntity
->slot()) // Talking again to yourself ?
370 if (selection
->Type
== CEntityCL::Player
)
372 setupContextMenuTalkWithPlayer();
375 if(selection
->properties().talkableTo())
377 if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
379 // Can talk with bot if not too far
380 CVectorD vect1
= selection
->pos();
381 CVectorD vect2
= UserEntity
->pos();
382 double distanceSquare
= pow(vect1
.x
-vect2
.x
,2) + pow(vect1
.y
-vect2
.y
,2);
383 if (distanceSquare
<= MaxTalkingDistSquare
)
385 updateContextMenuTalkEntries(availablePrograms
);
387 // Special case for buildings
388 if (distanceSquare
<= MaxTalkingOutpostBuildingDistSquare
)
389 _OkTextTradeOutpostBuilding
= ((availablePrograms
& (1 << BOTCHATTYPE::TradeOutpostBuilding
)) != 0);
397 // Action possible only if the client is not already busy and the selection is able to do this with you..
398 if(selection
&& selection
->properties().canExchangeItem())
399 _TextExchange
->setActive(!UserEntity
->isBusy());
401 _TextExchange
->setActive(false);
405 _TextFreeLook
->setActive(true);
408 _TextUnseat
->setActive(false);
409 // Enable extraction for a forage source
412 _TextExtractRM
->setActive(false);
413 if ( selection
&& selection
->isForageSource() )
414 _TextExtractRM
->setActive(true);
418 // Enable attack mode
420 _TextAttack
->setActive(canAttack());
422 if (_TextDuel
&& _TextUnDuel
)
424 if ((!UserEntity
->isRiding()) && (_ServerInDuel
->getValue8() != 0))
426 _TextDuel
->setActive(false);
427 _TextUnDuel
->setActive(true);
431 _TextDuel
->setActive(true);
432 _TextUnDuel
->setActive(false);
436 _TextDuel
->setActive(false);
437 _TextUnDuel
->setActive(false);
441 if (_TextPvpChallenge
&& _TextUnPvpChallenge
)
443 if ((!UserEntity
->isRiding()) && (_ServerInPvpChallenge
->getValue8() != 0))
445 _TextPvpChallenge
->setActive(false);
446 _TextUnPvpChallenge
->setActive(true);
448 else if (canPvpChallenge())
450 _TextPvpChallenge
->setActive(true);
451 _TextUnPvpChallenge
->setActive(false);
455 _TextPvpChallenge
->setActive(false);
456 _TextUnPvpChallenge
->setActive(false);
460 // Enable disengage mode
462 _TextDisengage
->setActive(canDisengage());
466 _TextMove
->setActive(!UserControls
.autowalkState());
467 // Enable Stop Autowalk
469 _TextStop
->setActive(UserControls
.autowalkState());
471 // Disable player properties
473 _TextInfo
->setActive(selection
&& (!selection
->isForageSource()));
478 // Action possible only if the client is not already busy and the selection is able to do this with you..
479 _TextFollow
->setActive(
481 (selection
->slot() != UserEntity
->slot()) &&
482 (!selection
->isForageSource()) &&
483 (selection
->isDead()==false) &&
484 (((availablePrograms
& (1 << BOTCHATTYPE::DontFollow
)) == 0)));
485 // See also below for mount/packer
491 // Action possible only if the client is not already busy and the selection is able to do this with you..
492 _TextAssist
->setActive(!R2::getEditor().isDMing() && selection
&& (selection
->slot() != UserEntity
->slot()) && (!selection
->isForageSource()) && (selection
->isDead()==false));
493 // See also below for mount/packer
499 bool invitable
= false;
500 // User should not be flagged as invitable by himself, so no need to check that selection is not the user
501 if(selection
&& selection
->properties().invitable() && propValidation
.invitable() )
505 // Grey/Ungrey the entry.
506 _TextInvit
->setActive(invitable
);
513 if(filterAvailablePrograms(_AvailablePrograms
->getValue32())&(1 << BOTCHATTYPE::GuildInviteFlag
))
514 _TextGuildInvit
->setActive (true);
516 _TextGuildInvit
->setActive (false);
519 // Active "Quit Team" if you are a member of one.
522 if (_ServerTeamPresent
)
524 _TextQuitTeam
->setActive( _ServerTeamPresent
->getValueBool() );
528 // Invite to friend list (only if target is a player, and not a friend already)
529 if(_TextAddToFriendList
)
531 _TextAddToFriendList
->setActive(false);
532 if (selection
&& selection
->Type
== CEntityCL::Player
)
534 if (!selection
->getEntityName().empty())
536 sint peopleIndex
= PeopleInterraction
.FriendList
.getIndexFromName(selection
->getEntityName());
537 if (peopleIndex
== -1) // not already in friend list
539 _TextAddToFriendList
->setActive(true);
547 _TextMount
->setActive(false);
548 if(selection
&& (selection
->isUserPackAnimal() || (selection
->isUserMount())))
550 // Get the index of the selected animal, if owned by the player
552 if ( ! selection
->getPackAnimalIndexInDB( animalIndex
) )
555 // Disable 'Mount' if server says so
556 CViewTextMenu
*pTextMount
= NULL
;
557 if ( propValidation
.mountable() )
558 pTextMount
= _TextMount
;
560 _TextMount
->setActive( false ); // pTextMount remains NULL
562 // Enable/disable various menu items
563 bool ok
= testMenuOptionForPackAnimal( selection
, animalIndex
, true, _TextPAFollow
, _TextPAStop
, _TextPAFree
,
564 _TextPAEnterStable
, NULL
/*no 'leave stable' in context menu*/, pTextMount
,
565 NULL
/*unmount always active in context menu when the character is riding*/, _TextPAEnterBag
, NULL
);
567 // Follow & assist special case
569 _TextFollow
->setActive( false ); // can't follow own pet
571 _TextAssist
->setActive( false ); // can't assist a pet
573 // Write the selected pack animal, for future "beast_order" action handler
576 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
577 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:GCM_BEAST_SELECTED", false);
578 // beast_order AH start with 1 (0 for ALL beasts)
580 node
->setValue32(animalIndex
+1);
586 _TextPAFollow
->setActive(false);
588 _TextPAStop
->setActive(false);
589 if (_TextPAEnterStable
)
590 _TextPAEnterStable
->setActive(false);
592 _TextPAEnterBag
->setActive(false);
595 // Remove Free option to prevent miss click
597 _TextPAFree
->setActive(false);
603 _TextBuildTotem
->setActive(false);
604 if( availablePrograms
& ( 1 << BOTCHATTYPE::Totem
) )
606 _TextBuildTotem
->setActive(true);
610 // Apply real activation of Talk Texts.
614 // ***************************************************************************
615 bool CGameContextMenu::canAttack()
617 if (R2::getEditor().isDMing()) return false;
619 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
621 if (UserEntity
->isFighting() || UserEntity
->isRiding())
624 // To enter in combat, the user should not be talking.
625 if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
627 // If there is a selection.
628 if (selection
&& selection
->isDead() == false)
630 uint32 availablePrograms
= (uint32
) filterAvailablePrograms(_AvailablePrograms
->getValue32());
632 if(selection
->properties().attackable() || (availablePrograms
& (1<<BOTCHATTYPE::Attackable
)))
639 // ***************************************************************************
640 bool CGameContextMenu::canDuel()
642 if (UserEntity
->isFighting() || UserEntity
->isRiding())
645 // To enter in combat, the user should not be talking.
646 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
649 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
650 if (selection
== NULL
)
653 if (selection
->isPlayer())
654 if (selection
->isDead() == false)
660 // ***************************************************************************
661 bool CGameContextMenu::canPvpChallenge()
663 if (UserEntity
->isFighting() || UserEntity
->isRiding())
666 // To enter in combat, the user should not be talking.
667 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
670 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
671 if (selection
== NULL
)
674 if (selection
->isPlayer())
675 if (selection
->isDead() == false)
681 // ***************************************************************************
682 bool CGameContextMenu::canDisengage()
684 if (UserEntity
->isFighting())
690 // ***************************************************************************
691 bool CGameContextMenu::canTeamKick()
693 CEntityCL
*selection
= EntitiesMngr
.entity(UserEntity
->selection());
694 if (selection
!= NULL
)
696 sint n
= PeopleInterraction
.TeamList
.getIndexFromName(selection
->getEntityName());
703 // ***************************************************************************
704 void CGameContextMenu::updateContextMenuMissionsOptions( bool forceHide
)
706 for(uint k
= 0; k
< NUM_MISSION_OPTIONS
; ++k
)
708 CViewTextMenu
*pVTM
= _TextMission
[k
];
711 if ( _MissionOption
[k
] && (!forceHide
) )
713 uint32 textID
= (uint32
) _MissionOption
[k
]->getValue32();
717 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID
, result
);
720 result
= NLMISC::CI18N::get("uiMissionOptionNotReceived");
722 pVTM
->setText(result
);
723 pVTM
->setActive(true);
728 pVTM
->setActive(false);
734 pVTM
->setActive(false);
740 // ***************************************************************************
741 void CGameContextMenu::updateContextMenuWebPage(uint options
)
743 // Show the web page (title must be present)
744 _OkTextWebPage
= ((options
& (1 << BOTCHATTYPE::WebPageFlag
)) != 0);
746 _OkTextWebPage
= _WebPageTitle
&& _WebPageTitle
->getValue32()!=0;
748 // Change the WebPage text, when available
749 CViewTextMenu
*pVTM
= _TextWebPage
;
754 uint32 textID
= (uint32
) _WebPageTitle
->getValue32();
758 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID
, result
);
761 result
= NLMISC::CI18N::get("uiWebPageNameNotReceived");
763 pVTM
->setText(result
);
777 if (_TextWebPage
) _TextWebPage
->setActive(_OkTextWebPage
);
780 // ***************************************************************************
781 void CGameContextMenu::updateContextMenuOutpostState(uint options
)
783 CSheetId outpostSheet
;
786 _OkTextOutpostState
= false;
787 if ( (options
& (1 << BOTCHATTYPE::OutpostFlag
)) != 0 && _OutpostSheet
)
789 // check that the outpost sheet is correct
790 outpostSheet
= _OutpostSheet
->getValue32();
791 CEntitySheet
*s
= SheetMngr
.get(outpostSheet
);
792 if(s
&& s
->Type
== CEntitySheet::OUTPOST
)
793 _OkTextOutpostState
= true;
797 if(_OkTextOutpostState
)
799 CViewTextMenu
*pVTM
= _TextOutpostState
;
801 pVTM
->setText(STRING_MANAGER::CStringManagerClient::getOutpostLocalizedName(outpostSheet
));
805 if (_TextOutpostState
) _TextOutpostState
->setActive(_OkTextOutpostState
);
808 // ***************************************************************************
809 void CGameContextMenu::updateContextMenuOutpostBanish()
811 bool okForBanPlayer
= false;
812 bool okForBanGuild
= false;
814 // Test if the player can ban the targeted player / player's guild
815 extern void outpostTestUserCanBan(CCDBNodeLeaf
*dbBanRight
, bool &, bool &);
816 outpostTestUserCanBan(_OutpostRightToBannish
, okForBanPlayer
, okForBanGuild
);
819 if(_TextOutpostBanishPlayer
) _TextOutpostBanishPlayer
->setActive(okForBanPlayer
);
820 if(_TextOutpostBanishGuild
) _TextOutpostBanishGuild
->setActive(okForBanGuild
);
823 // ***************************************************************************
824 void CGameContextMenu::updateContextMenuMissionRing()
826 for(uint k
= 0; k
< BOTCHATTYPE::MaxR2MissionEntryDatabase
; ++k
)
828 CViewTextMenu
*pVTM
= _TextMissionRing
[k
];
832 if ( _MissionRing
[k
] )
833 textId
= _MissionRing
[k
]->getValue32();
834 // if the textId is ok and Flag is set.
838 bool res
= STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, result
);
841 result
= NLMISC::CI18N::get("uiMissionRingNameNotReceived");
843 pVTM
->setText(result
);
844 pVTM
->setActive(true);
849 pVTM
->setActive(false);
855 // ***************************************************************************
856 void CGameContextMenu::updateContextMenuTalkEntries(uint options
)
860 options
= std::numeric_limits
<uint
>::max(); // in local mode, force all options to be shown (for debug)
863 _OkTextNews
= ((options
& (1 << BOTCHATTYPE::NewsFlag
)));
865 _OkTextTradeItem
= ((options
& (1 << BOTCHATTYPE::TradeItemFlag
)) != 0);
866 _OkTextTradeTeleport
= ((options
& (1 << BOTCHATTYPE::TradeTeleportFlag
)) != 0);
867 _OkTextTradeFaction
= ((options
& (1 << BOTCHATTYPE::TradeFactionFlag
)) != 0);
868 _OkTextTradeCosmetic
= ((options
& (1 << BOTCHATTYPE::TradeCosmeticFlag
)) != 0);
869 _OkTextTradeGuildOptions
= ((options
& (1 << BOTCHATTYPE::TradeBuildingOptions
)) != 0);
870 _OkTextTradeOutpostBuilding
= ((options
& (1 << BOTCHATTYPE::TradeOutpostBuilding
)) != 0);
871 _OkTextTradeGuildRoleMaster
= ((options
& (1 << BOTCHATTYPE::GuildRoleMaster
)) != 0);
872 _OkTextTradePact
= ((options
& (1 << BOTCHATTYPE::TradePactFlag
)) != 0);
873 _OkTextTradePhrase
= ((options
& (1 << BOTCHATTYPE::TradePhraseFlag
)) != 0);
875 _OkTextChooseMission
= ((options
& (1 << BOTCHATTYPE::ChooseMissionFlag
)) != 0);
877 _OkTextCreateGuild
= ((options
& (1 << BOTCHATTYPE::CreateGuildFlag
)) != 0);
879 _OkTextChooseZCCharge
= ((options
& (1 << BOTCHATTYPE::AskGuildDutyFlag
)) != 0);
880 _OkTextCancelZCCharge
= ((options
& (1 << BOTCHATTYPE::CancelGuildDutyFlag
)) != 0);
882 /*_OkTextBuyRM= ((options & (1 << BOTCHATTYPE::)) != 0);
883 _OkTextUpgradeRM= ((options & (1 << BOTCHATTYPE::)) != 0);
884 _OkTextDestroyBuilding= ((options & (1 << BOTCHATTYPE::)) != 0);*/
885 // TODO BOTCHAT: RM Buy/Upgrade.
886 // TODO BOTCHAT: Declare war no more through "Mission Option"
887 // TODO BOTCHAT: Destroy Building only if already created
888 // TODO BOTCHAT: ZCBuilder is deprecated, as is _OkTextChooseBuilding
889 // TODO BOTCHAT: _OkTextDynamicMission is deprecated
890 _OkTextDynamicMission
= false;
892 _OkTextUpgradeRM
= false;
893 _OkTextChooseBuilding
= false;
894 _OkTextDestroyBuilding
= _OkTextChooseBuilding
;
898 // ***************************************************************************
899 void CGameContextMenu::setupContextMenuCantTalk()
901 updateContextMenuTalkEntries(0);
905 // ***************************************************************************
906 void CGameContextMenu::setupContextMenuTalkWithPlayer()
911 // ***************************************************************************
912 void CGameContextMenu::applyTextTalk()
914 if (_TextNews
) _TextNews
->setActive(_OkTextNews
);
915 if (_TextTradeItem
) _TextTradeItem
->setActive(_OkTextTradeItem
);
916 if (_TextTradeTeleport
) _TextTradeTeleport
->setActive(_OkTextTradeTeleport
);
917 if (_TextTradeFaction
) _TextTradeFaction
->setActive(_OkTextTradeFaction
);
918 if (_TextTradeCosmetic
) _TextTradeCosmetic
->setActive(_OkTextTradeCosmetic
);
919 if (_TextTradeGuildOptions
) _TextTradeGuildOptions
->setActive(_OkTextTradeGuildOptions
);
920 if (_TextTradeOutpostBuilding
) _TextTradeOutpostBuilding
->setActive(_OkTextTradeOutpostBuilding
);
921 if (_TextTradeGuildRoleMaster
) _TextTradeGuildRoleMaster
->setActive(_OkTextTradeGuildRoleMaster
);
922 if (_TextTradePact
) _TextTradePact
->setActive(_OkTextTradePact
);
923 if (_TextTradePhrase
) _TextTradePhrase
->setActive(_OkTextTradePhrase
);
924 if (_TextChooseMission
) _TextChooseMission
->setActive(_OkTextChooseMission
);
925 if (_TextCreateGuild
)
927 _TextCreateGuild
->setActive(_OkTextCreateGuild
);
928 // If the player is already in a guild set the text grayed
929 _TextCreateGuild
->setGrayed(CGuildManager::getInstance()->isInGuild());
932 if (_TextDynamicMission
) _TextDynamicMission
->setActive(_OkTextDynamicMission
);
933 if (_TextTalk
) _TextTalk
->setActive(_OkTextTalk
);
934 if (_TextChooseZCCharge
) _TextChooseZCCharge
->setActive(_OkTextChooseZCCharge
);
935 if (_TextChooseBuilding
) _TextChooseBuilding
->setActive(_OkTextChooseBuilding
);
936 if (_TextBuyRM
) _TextBuyRM
->setActive(_OkTextBuyRM
);
937 if (_TextUpgradeRM
) _TextUpgradeRM
->setActive(_OkTextUpgradeRM
);
938 if (_TextCancelZCCharge
) _TextCancelZCCharge
->setActive(_OkTextCancelZCCharge
);
939 if (_TextDestroyBuilding
) _TextDestroyBuilding
->setActive(_OkTextDestroyBuilding
);
942 // ***************************************************************************
945 * Enable/disable various menu items for animals.
946 * selectedAnimalInVision can be NULL (out of vision)
947 * index can be -1 (no owned animal)
948 * Any CViewTextMenu* can be NULL
950 bool testMenuOptionForPackAnimal( CEntityCL
* selectedAnimalInVision
, uint index
, bool clearAll
,
951 CViewTextMenu
*pFollow
, CViewTextMenu
*pStop
, CViewTextMenu
*pFree
,
952 CViewTextMenu
*pEnterStable
, CViewTextMenu
*pLeaveStable
,
953 CViewTextMenu
*pMount
, CViewTextMenu
*pUnmount
,
954 CViewTextMenu
*pEnterBag
, CViewTextMenu
*pLeaveBag
)
958 // Disable and gray all by default
959 if(pFollow
) { pFollow
->setActive(false); pFollow
->setGrayed(true); }
960 if(pStop
) { pStop
->setActive(false); pStop
->setGrayed(true); }
961 if(pFree
) { pFree
->setActive(false); pFree
->setGrayed(true); }
962 if(pEnterStable
) { pEnterStable
->setActive(false); pEnterStable
->setGrayed(true); }
963 if(pLeaveStable
) { pLeaveStable
->setActive(false); pLeaveStable
->setGrayed(true); }
964 if(pEnterBag
) { pEnterBag
->setActive(false); pEnterBag
->setGrayed(true); }
965 if(pLeaveBag
) { pLeaveBag
->setActive(false); pLeaveBag
->setGrayed(false); }
966 if(pMount
) { pMount
->setActive(false); pMount
->setGrayed(true); }
967 if(pUnmount
) { pUnmount
->setActive(false); pUnmount
->setGrayed(true); }
970 // Don't enable anything if index not found (e.g. the character is not the owner of the animal)
971 if ( (index
== (uint
)-1) || (!UserEntity
) )
974 // Get animal status and type
975 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
976 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS", index
), false);
977 if(!node
) return false;
978 ANIMAL_STATUS::EAnimalStatus status
= (ANIMAL_STATUS::EAnimalStatus
)node
->getValue32();
979 node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:TYPE", index
), false);
980 if(!node
) return false;
981 ANIMAL_TYPE::EAnimalType anitype
= (ANIMAL_TYPE::EAnimalType
)node
->getValue32();
983 if (anitype
!= ANIMAL_TYPE::Pet
)
986 pEnterBag
->setActive(false);
988 pLeaveBag
->setActive(false);
991 // COMMON PART FOR ALL TYPES OF ANIMAL
993 // Is the character mounted on the animal?
994 bool userIsMountedOnIt
= false;
995 if ( selectedAnimalInVision
&& (anitype
== ANIMAL_TYPE::Mount
) && UserEntity
->isRiding() )
997 uint8 mountSlot
= (uint8
)IngameDbMngr
.getProp( "Entities:E" + toString(UserEntity
->slot()) + ":P" + toString(CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID
));
998 userIsMountedOnIt
= (mountSlot
== selectedAnimalInVision
->slot());
1001 bool onLandscape
= ANIMAL_STATUS::isInLandscape(status
);
1002 double distanceSquare
= 0;
1003 if ( selectedAnimalInVision
)
1005 CVectorD vect1
= selectedAnimalInVision
->pos();
1006 CVectorD vect2
= UserEntity
->pos();
1007 distanceSquare
= pow(vect1
.x
-vect2
.x
,2) + pow(vect1
.y
-vect2
.y
,2);
1010 bool onBag
= ANIMAL_STATUS::isInBag(status
);
1012 // Enable option only if pack animal present
1013 if(ANIMAL_STATUS::isSpawned(status
))
1015 bool canEnterLeaveStable
= ANIMAL_STATUS::canEnterLeaveStable(status
);
1017 if (!userIsMountedOnIt
)
1019 if(pFollow
&& onLandscape
) pFollow
->setActive(true);
1020 if(pStop
&& onLandscape
) pStop
->setActive(true);
1022 // Enter/leave stable are only displayed when near a stable ('canEnterLeaveStable')
1023 if(pEnterStable
&& onLandscape
&& canEnterLeaveStable
) pEnterStable
->setActive(true);
1024 if(pLeaveStable
&& ANIMAL_STATUS::isInStable(status
) && canEnterLeaveStable
) pLeaveStable
->setActive(true);
1026 // Can always free, dead/alive, in or out stable animals
1029 pFree
->setActive(true);
1030 pFree
->setGrayed(false);
1034 // If alive (and close to the character), ungray all
1035 if(ANIMAL_STATUS::isAlive(status
))
1037 if (onLandscape
&& selectedAnimalInVision
&& (distanceSquare
<= MaxAnimalCommandDistSquare
))
1039 if(pFollow
) pFollow
->setGrayed(false);
1040 if(pStop
) pStop
->setGrayed(false);
1041 if(pEnterStable
) pEnterStable
->setGrayed(false);
1042 if (pEnterBag
&& !onBag
)
1043 pEnterBag
->setGrayed(false);
1045 if (pLeaveBag
&& onBag
)
1046 pLeaveBag
->setActive(true);
1048 if (pEnterBag
&& !onBag
&& anitype
== ANIMAL_TYPE::Pet
)
1049 pEnterBag
->setActive(true);
1051 if(pLeaveStable
) pLeaveStable
->setGrayed(false);
1055 // Specific part for mountable animal
1056 if ((anitype
== ANIMAL_TYPE::Mount
) &&
1057 (ANIMAL_STATUS::isSpawned(status
)) && onLandscape
)
1059 if ( userIsMountedOnIt
)
1061 // Always allow to unmount the mounted mount
1062 if(pUnmount
) pUnmount
->setActive(true);
1063 if(pUnmount
) pUnmount
->setGrayed(false);
1068 ((!selectedAnimalInVision
) || selectedAnimalInVision
->properties().mountable()))
1070 // Display 'Mount' if the entity is of mountable type
1071 pMount
->setActive(true);
1073 // Enable 'Mount' if the character is not busy and the entity is alive and close enough
1074 if(ANIMAL_STATUS::isAlive(status
) && (!UserEntity
->isRiding()) &&
1075 (!UserEntity
->isFighting()) && (!UserEntity
->isBusy()))
1077 if(selectedAnimalInVision
&& (distanceSquare
<= MaxAnimalCommandDistSquare
))
1079 pMount
->setGrayed(false);