Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / game_context_menu.cpp
blob3a283022c6b8b1fb6bbf6d7809be7a9f515382e4
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
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>
7 //
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/>.
24 /////////////
25 // INCLUDE //
26 /////////////
27 #include "stdpch.h"
28 // Client.
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"
33 #include "entities.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"
41 // GAME SHARE
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;
51 using namespace std;
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()
64 _GroupMenu = NULL;
66 _MilkoAttackDisengage = NULL;
67 _ContextVal = NULL;
68 _AvailablePrograms = NULL;
69 _ServerTeamPresent = NULL;
70 for(uint i=0;i<NUM_MISSION_OPTIONS;i++)
71 _MissionOption[i]= NULL;
72 _ServerInDuel = NULL;
73 _ServerInPvpChallenge = NULL;
74 _WebPageTitle = NULL;
75 _OutpostSheet= 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());
94 return;
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";
104 else
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.");
112 return;
115 // Some DB links
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);
125 // Some text Menu
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);
165 // BotChat menus
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";
192 // Pack Animals
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";
199 // Forage source
200 _TextExtractRM= "ui:interface:" + menuId + ":extract_rm";
202 // Build Spire
203 _TextBuildTotem= "ui:interface:" + menuId + ":build_totem";
207 // ***************************************************************************
208 // tmp for debug
209 bool ForceTalkWithBot = false;
210 bool ForceTalkWithPlayer = false;
212 // ***************************************************************************
213 void CGameContextMenu::update()
215 H_AUTO (RZ_Interface_updateContextMenu )
217 if( !_ContextVal || !_GroupMenu )
218 return;
220 CProperties propValidation = CProperties(_ContextVal->getValue16());
222 // botChatPrograms
223 uint32 availablePrograms = filterAvailablePrograms((uint32) _AvailablePrograms->getValue32());
225 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
227 // Milko Pad
228 if ((_GroupMilkoPad != NULL) && (_GroupMilkoPad->getActive()))
230 if (canDisengage())
232 _MilkoAttackDisengage->setValue32(1);
233 if (_MilkoAttDisBut1)
234 _MilkoAttDisBut1->setHardText("uiMk_action5_1");
235 if (_MilkoAttDisBut2)
236 _MilkoAttDisBut2->setHardText("uiMk_action5_1");
238 else
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())
250 return;
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())
267 // Loot
268 if(_TextLootAction)
269 _TextLootAction->setActive(false);
270 // Quartering
271 if(_TextQuartering)
272 _TextQuartering->setActive(false);
273 // Disable talk, unless with a player
274 if (ForceTalkWithBot) // tmp
276 updateContextMenuTalkEntries(availablePrograms);
278 else if (ForceTalkWithPlayer)
280 setupContextMenuTalkWithPlayer();
282 else
283 if(selection && selection->Type == CEntityCL::Player)
285 setupContextMenuTalkWithPlayer();
288 // Exchange
289 if(_TextExchange)
290 _TextExchange->setActive(false);
291 // Disable mount
292 if(_TextMount)
293 _TextMount->setActive(false);
296 // Disable FreeLook.
297 if(_TextFreeLook)
298 _TextFreeLook->setActive(false);
299 // Disable unseat.
300 if(_TextUnseat)
301 _TextUnseat->setActive(false);
302 // Disable extraction
303 if(_TextExtractRM)
304 _TextExtractRM->setActive(false);
306 // Mount
307 else if(UserEntity->isRiding())
309 // Loot
310 if(_TextLootAction)
311 _TextLootAction->setActive(false);
312 // Quartering
313 if(_TextQuartering)
314 _TextQuartering->setActive(false);
315 // No talk when riding
316 // No exchange when riding
317 if(_TextExchange)
318 _TextExchange->setActive(false);
320 // Disable mount
321 if(_TextMount)
322 _TextMount->setActive(false);
325 // Disable Free Look
326 if(_TextFreeLook)
327 _TextFreeLook->setActive(false);
328 // Enable unseat
329 if(_TextUnseat)
330 _TextUnseat->setActive(true);
331 // Disable extraction
332 if(_TextExtractRM)
333 _TextExtractRM->setActive(false);
335 // Not in combat or riding mode.
336 else
338 // Loot
339 if(_TextLootAction)
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);
348 // Quartering
349 if(_TextQuartering)
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);
356 // talk ?
357 if (ForceTalkWithBot) // tmp
359 updateContextMenuTalkEntries(availablePrograms);
361 else if (ForceTalkWithPlayer)
363 setupContextMenuTalkWithPlayer();
365 else
366 if(UserEntity->selection() != UserEntity->slot()) // Talking again to yourself ?
368 if(selection)
370 if (selection->Type == CEntityCL::Player)
372 setupContextMenuTalkWithPlayer();
374 else
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);
394 // Exchange
395 if(_TextExchange)
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());
400 else
401 _TextExchange->setActive(false);
403 // Enable Free Look
404 if(_TextFreeLook)
405 _TextFreeLook->setActive(true);
406 // Disable unseat
407 if(_TextUnseat)
408 _TextUnseat->setActive(false);
409 // Enable extraction for a forage source
410 if(_TextExtractRM)
412 _TextExtractRM->setActive(false);
413 if ( selection && selection->isForageSource() )
414 _TextExtractRM->setActive(true);
418 // Enable attack mode
419 if (_TextAttack)
420 _TextAttack->setActive(canAttack());
422 if (_TextDuel && _TextUnDuel)
424 if ((!UserEntity->isRiding()) && (_ServerInDuel->getValue8() != 0))
426 _TextDuel->setActive(false);
427 _TextUnDuel->setActive(true);
429 else if (canDuel())
431 _TextDuel->setActive(true);
432 _TextUnDuel->setActive(false);
434 else
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);
453 else
455 _TextPvpChallenge->setActive(false);
456 _TextUnPvpChallenge->setActive(false);
460 // Enable disengage mode
461 if (_TextDisengage)
462 _TextDisengage->setActive(canDisengage());
464 // Enable Autowalk
465 if(_TextMove)
466 _TextMove->setActive(!UserControls.autowalkState());
467 // Enable Stop Autowalk
468 if(_TextStop)
469 _TextStop->setActive(UserControls.autowalkState());
471 // Disable player properties
472 if(_TextInfo)
473 _TextInfo->setActive(selection && (!selection->isForageSource()));
475 // Follow
476 if(_TextFollow)
478 // Action possible only if the client is not already busy and the selection is able to do this with you..
479 _TextFollow->setActive(
480 selection &&
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
488 // Assist
489 if(_TextAssist)
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
496 // Invite
497 if(_TextInvit)
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() )
503 invitable = true;
505 // Grey/Ungrey the entry.
506 _TextInvit->setActive(invitable);
509 // Guild Invit
510 if(_TextGuildInvit)
512 // if server OK.
513 if(filterAvailablePrograms(_AvailablePrograms->getValue32())&(1 << BOTCHATTYPE::GuildInviteFlag))
514 _TextGuildInvit->setActive (true);
515 else
516 _TextGuildInvit->setActive (false);
519 // Active "Quit Team" if you are a member of one.
520 if(_TextQuitTeam)
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);
545 // Pack/Mount Animal
546 if ( _TextMount )
547 _TextMount->setActive(false);
548 if(selection && (selection->isUserPackAnimal() || (selection->isUserMount())))
550 // Get the index of the selected animal, if owned by the player
551 sint animalIndex;
552 if ( ! selection->getPackAnimalIndexInDB( animalIndex ) )
553 animalIndex = -1;
555 // Disable 'Mount' if server says so
556 CViewTextMenu *pTextMount = NULL;
557 if ( propValidation.mountable() )
558 pTextMount = _TextMount;
559 else if (_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
568 if ( _TextFollow )
569 _TextFollow->setActive( false ); // can't follow own pet
570 if ( _TextAssist )
571 _TextAssist->setActive( false ); // can't assist a pet
573 // Write the selected pack animal, for future "beast_order" action handler
574 if(ok)
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)
579 if(node)
580 node->setValue32(animalIndex+1);
583 else
585 if (_TextPAFollow)
586 _TextPAFollow->setActive(false);
587 if (_TextPAStop)
588 _TextPAStop->setActive(false);
589 if (_TextPAEnterStable)
590 _TextPAEnterStable->setActive(false);
591 if (_TextPAEnterBag)
592 _TextPAEnterBag->setActive(false);
595 // Remove Free option to prevent miss click
596 if (_TextPAFree)
597 _TextPAFree->setActive(false);
600 // build spire
601 if(_TextBuildTotem)
603 _TextBuildTotem->setActive(false);
604 if( availablePrograms & ( 1 << BOTCHATTYPE::Totem ) )
606 _TextBuildTotem->setActive(true);
610 // Apply real activation of Talk Texts.
611 applyTextTalk();
614 // ***************************************************************************
615 bool CGameContextMenu::canAttack()
617 if (R2::getEditor().isDMing()) return false;
618 bool ret = false;
619 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
621 if (UserEntity->isFighting() || UserEntity->isRiding())
622 return ret;
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)))
633 ret = true;
636 return ret;
639 // ***************************************************************************
640 bool CGameContextMenu::canDuel()
642 if (UserEntity->isFighting() || UserEntity->isRiding())
643 return false;
645 // To enter in combat, the user should not be talking.
646 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
647 return false;
649 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
650 if (selection == NULL)
651 return false;
653 if (selection->isPlayer())
654 if (selection->isDead() == false)
655 return true;
657 return false;
660 // ***************************************************************************
661 bool CGameContextMenu::canPvpChallenge()
663 if (UserEntity->isFighting() || UserEntity->isRiding())
664 return false;
666 // To enter in combat, the user should not be talking.
667 if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
668 return false;
670 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
671 if (selection == NULL)
672 return false;
674 if (selection->isPlayer())
675 if (selection->isDead() == false)
676 return true;
678 return false;
681 // ***************************************************************************
682 bool CGameContextMenu::canDisengage()
684 if (UserEntity->isFighting())
685 return true;
686 else
687 return false;
690 // ***************************************************************************
691 bool CGameContextMenu::canTeamKick()
693 CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
694 if (selection != NULL)
696 sint n = PeopleInterraction.TeamList.getIndexFromName(selection->getEntityName());
697 if (n >= 0)
698 return true;
700 return false;
703 // ***************************************************************************
704 void CGameContextMenu::updateContextMenuMissionsOptions( bool forceHide )
706 for(uint k = 0; k < NUM_MISSION_OPTIONS; ++k)
708 CViewTextMenu *pVTM = _TextMission[k];
709 if (pVTM)
711 if ( _MissionOption[k] && (!forceHide) )
713 uint32 textID = (uint32) _MissionOption[k]->getValue32();
714 if (textID)
716 string result;
717 bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID, result);
718 if (!res)
720 result = NLMISC::CI18N::get("uiMissionOptionNotReceived");
722 pVTM->setText(result);
723 pVTM->setActive(true);
725 else
727 pVTM->setText("");
728 pVTM->setActive(false);
731 else
733 pVTM->setText("");
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);
745 if(_OkTextWebPage)
746 _OkTextWebPage= _WebPageTitle && _WebPageTitle->getValue32()!=0;
748 // Change the WebPage text, when available
749 CViewTextMenu *pVTM = _TextWebPage;
750 if (pVTM)
752 if ( _WebPageTitle )
754 uint32 textID = (uint32) _WebPageTitle->getValue32();
755 if (textID)
757 string result;
758 bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID, result);
759 if (!res)
761 result = NLMISC::CI18N::get("uiWebPageNameNotReceived");
763 pVTM->setText(result);
765 else
767 pVTM->setText("");
770 else
772 pVTM->setText("");
776 // apply the active
777 if (_TextWebPage) _TextWebPage->setActive(_OkTextWebPage);
780 // ***************************************************************************
781 void CGameContextMenu::updateContextMenuOutpostState(uint options)
783 CSheetId outpostSheet;
785 // Outpost ok?
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;
796 // Fill the text
797 if(_OkTextOutpostState)
799 CViewTextMenu *pVTM = _TextOutpostState;
800 if (pVTM)
801 pVTM->setText(STRING_MANAGER::CStringManagerClient::getOutpostLocalizedName(outpostSheet));
804 // apply the active
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);
818 // validate text
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];
829 if (pVTM)
831 uint32 textId= 0;
832 if ( _MissionRing[k] )
833 textId= _MissionRing[k]->getValue32();
834 // if the textId is ok and Flag is set.
835 if ( textId )
837 string result;
838 bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, result);
839 if (!res)
841 result = NLMISC::CI18N::get("uiMissionRingNameNotReceived");
843 pVTM->setText(result);
844 pVTM->setActive(true);
846 else
848 pVTM->setText("");
849 pVTM->setActive(false);
855 // ***************************************************************************
856 void CGameContextMenu::updateContextMenuTalkEntries(uint options)
858 if (ClientCfg.Local)
860 options = std::numeric_limits<uint>::max(); // in local mode, force all options to be shown (for debug)
862 // news
863 _OkTextNews= ((options & (1 << BOTCHATTYPE::NewsFlag)));
864 // trade
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);
874 // choose mission
875 _OkTextChooseMission= ((options & (1 << BOTCHATTYPE::ChooseMissionFlag)) != 0);
876 // create guild
877 _OkTextCreateGuild= ((options & (1 << BOTCHATTYPE::CreateGuildFlag)) != 0);
878 // New Yoyo BotChat
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;
891 _OkTextBuyRM= false;
892 _OkTextUpgradeRM= false;
893 _OkTextChooseBuilding= false;
894 _OkTextDestroyBuilding= _OkTextChooseBuilding;
898 // ***************************************************************************
899 void CGameContextMenu::setupContextMenuCantTalk()
901 updateContextMenuTalkEntries(0);
902 _OkTextTalk= false;
905 // ***************************************************************************
906 void CGameContextMenu::setupContextMenuTalkWithPlayer()
908 _OkTextTalk= true;
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)
956 if ( clearAll )
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) )
972 return false;
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)
985 if (pEnterBag)
986 pEnterBag->setActive(false);
987 if (pLeaveBag)
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
1027 if(pFree)
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);
1065 else
1067 if(pMount &&
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);
1086 return true;