khanat-code-old/code/ryzom/client/src/game_context_menu.cpp
2010-05-15 18:47:21 +02:00

1057 lines
34 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////
// INCLUDE //
/////////////
#include "stdpch.h"
// Client.
#include "game_context_menu.h"
#include "interface_v3/interface_manager.h"
#include "interface_v3/ctrl_text_button.h"
#include "interface_v3/group_menu.h"
#include "entities.h"
#include "interface_v3/bot_chat_manager.h"
#include "interface_v3/guild_manager.h"
#include "interface_v3/people_interraction.h"
#include "main_loop.h"
#include "interface_v3/inventory_manager.h"
#include "motion/user_controls.h"
#include "sheet_manager.h"
// GAME SHARE
#include "game_share/constants.h"
#include "game_share/properties.h"
#include "game_share/bot_chat_types.h"
#include "game_share/animal_type.h"
//
#include "r2/editor.h"
using namespace NLMISC;
using namespace std;
// filter available programs depending on R2 mode
static uint32 filterAvailablePrograms(uint32 src)
{
return R2::getEditor().isDMing() ? 0 : src;
}
// ***************************************************************************
CGameContextMenu::CGameContextMenu()
{
_GroupMenu = NULL;
_MilkoAttackDisengage = NULL;
_ContextVal = NULL;
_AvailablePrograms = NULL;
_ServerTeamPresent = NULL;
for(uint i=0;i<NUM_MISSION_OPTIONS;i++)
_MissionOption[i]= NULL;
_ServerInDuel = NULL;
_ServerInPvpChallenge = NULL;
_WebPageTitle = NULL;
_OutpostSheet= NULL;
_OutpostRightToBannish= NULL;
for(uint i=0;i<BOTCHATTYPE::MaxR2MissionEntryDatabase;i++)
_MissionRing[i]= NULL;
}
// ***************************************************************************
void CGameContextMenu::init(const std::string &srcMenuId)
{
std::string menuId = srcMenuId.empty() ? std::string("game_context_menu") : srcMenuId;
CInterfaceManager *pIM= CInterfaceManager::getInstance();
_GroupMenu = dynamic_cast<CGroupMenu*>(pIM->getWindowFromId ("ui:interface:" + menuId + ""));
_ContextVal = pIM->getDbProp("SERVER:TARGET:CONTEXT_VAL", false);
if(_GroupMenu == NULL)
{
nlwarning(("gamecontextmenu:init: 'ui:interface:" + menuId + "' window does not exist.").c_str());
return;
}
_GroupMilkoPad = "ui:interface:milko_pad";
if(_GroupMilkoPad != NULL)
{
_MilkoAttackDisengage = pIM->getDbProp("UI:VARIABLES:MK_ATTACK", false);
_MilkoAttDisBut1 = "ui:interface:milko_pad:content:mode1:mode1_content:milko_actions:action5";
_MilkoAttDisBut2 = "ui:interface:milko_pad:content:mode2:action5";
}
else
{
nlwarning("gamecontextmenu:init: 'ui:interface:milko_pad' window does not exist.");
}
if(_ContextVal == NULL)
{
nlwarning("gamecontextmenu:init: 'SERVER:TARGET:CONTEXT_VAL' node does not exist.");
return;
}
// Some DB links
_AvailablePrograms = pIM->getDbProp("LOCAL:TARGET:CONTEXT_MENU:PROGRAMMES");
_ServerTeamPresent = pIM->getDbProp(TEAM_DB_PATH ":0:PRESENT", false);
_ServerInDuel = pIM->getDbProp("SERVER:USER:IN_DUEL", false);
_ServerInPvpChallenge = pIM->getDbProp("SERVER:USER:IN_PVP_CHALLENGE", false);
_WebPageTitle = pIM->getDbProp("LOCAL:TARGET:CONTEXT_MENU:WEB_PAGE_TITLE", false);
_OutpostSheet = pIM->getDbProp("LOCAL:TARGET:CONTEXT_MENU:OUTPOST", false);
_OutpostRightToBannish = pIM->getDbProp("SERVER:CHARACTER_INFO:PVP_OUTPOST:RIGHT_TO_BANISH", false);
// Some text Menu
_TextLootAction = "ui:interface:" + menuId + ":loot_action";
_TextQuartering = "ui:interface:" + menuId + ":quartering";
_TextAttack = "ui:interface:" + menuId + ":attack";
_TextDuel = "ui:interface:" + menuId + ":duel";
_TextUnDuel = "ui:interface:" + menuId + ":unduel";
_TextPvpChallenge = "ui:interface:" + menuId + ":pvp_challenge";
_TextUnPvpChallenge = "ui:interface:" + menuId + ":unpvp_challenge";
_TextExchange = "ui:interface:" + menuId + ":exchange";
_TextMount = "ui:interface:" + menuId + ":mount";
_TextFreeLook = "ui:interface:" + menuId + ":free_look";
_TextMove = "ui:interface:" + menuId + ":move";
_TextStop = "ui:interface:" + menuId + ":stop";
_TextDisengage = "ui:interface:" + menuId + ":disengage";
_TextUnseat = "ui:interface:" + menuId + ":unseat";
_TextInfo = "ui:interface:" + menuId + ":info";
_TextFollow = "ui:interface:" + menuId + ":follow";
_TextAssist = "ui:interface:" + menuId + ":assist";
_TextInvit = "ui:interface:" + menuId + ":invit";
_TextGuildInvit = "ui:interface:" + menuId + ":guild_invit";
_TextQuitTeam = "ui:interface:" + menuId + ":quit_team";
_TextAddToFriendList = "ui:interface:" + menuId + ":add_to_friend_list";
_TextTalk = "ui:interface:" + menuId + ":talk";
// Mission DB and Text link
for(uint k = 0; k < NUM_MISSION_OPTIONS; ++k)
{
_MissionOption[k] = pIM->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSIONS_OPTIONS:%d:TITLE", (int) k), false);
_TextMission[k] = toString(("ui:interface:" + menuId + ":mo%d").c_str(), (int) k);
}
// Mission Ring DB and Text link
for(uint k = 0; k < BOTCHATTYPE::MaxR2MissionEntryDatabase; ++k)
{
_MissionRing[k]= pIM->getDbProp(toString("LOCAL:TARGET:CONTEXT_MENU:MISSION_RING:%d:TITLE", k), false);
_TextMissionRing[k] = toString(("ui:interface:" + menuId + ":mr%d").c_str(), (int) k);
}
// BotChat menus
_TextNews = "ui:interface:" + menuId + ":news";
_TextTradeItem = "ui:interface:" + menuId + ":trade_item";
_TextTradeTeleport = "ui:interface:" + menuId + ":trade_teleport";
_TextTradeFaction = "ui:interface:" + menuId + ":trade_faction";
_TextTradeCosmetic = "ui:interface:" + menuId + ":trade_cosmetic";
_TextTradeGuildOptions = "ui:interface:" + menuId + ":trade_guild_options";
_TextTradeOutpostBuilding = "ui:interface:" + menuId + ":trade_outpost_building";
_TextTradeGuildRoleMaster = "ui:interface:" + menuId + ":trade_guild_role_master";
_TextTradePact = "ui:interface:" + menuId + ":trade_pact";
_TextTradePhrase = "ui:interface:" + menuId + ":trade_phrase";
_TextChooseMission = "ui:interface:" + menuId + ":choose_mission";
_TextCreateGuild = "ui:interface:" + menuId + ":create_guild";
_TextDynamicMission = "ui:interface:" + menuId + ":dynamic_mission";
_TextChooseZCCharge= "ui:interface:" + menuId + ":choose_zc_charge";
_TextChooseBuilding= "ui:interface:" + menuId + ":choose_building";
_TextBuyRM= "ui:interface:" + menuId + ":buy_rm";
_TextUpgradeRM= "ui:interface:" + menuId + ":upgrade_rm";
_TextCancelZCCharge= "ui:interface:" + menuId + ":cancel_zc_charge";
_TextDestroyBuilding= "ui:interface:" + menuId + ":destroy_building";
_TextOutpostState= "ui:interface:" + menuId + ":outpost_state";
_TextWebPage= "ui:interface:" + menuId + ":web_page";
_TextOutpostBanishPlayer= "ui:interface:" + menuId + ":outpost_bannish_player";
_TextOutpostBanishGuild= "ui:interface:" + menuId + ":outpost_bannish_guild";
// Pack Animals
_TextPAFollow= "ui:interface:" + menuId + ":pa_follow";
_TextPAStop= "ui:interface:" + menuId + ":pa_stop";
_TextPAFree= "ui:interface:" + menuId + ":pa_free";
_TextPAEnterStable= "ui:interface:" + menuId + ":pa_enter_stable";
// Forage source
_TextExtractRM= "ui:interface:" + menuId + ":extract_rm";
// Build Spire
_TextBuildTotem= "ui:interface:" + menuId + ":build_totem";
}
// ***************************************************************************
// tmp for debug
bool ForceTalkWithBot = false;
bool ForceTalkWithPlayer = false;
// ***************************************************************************
void CGameContextMenu::update()
{
H_AUTO (RZ_Interface_updateContextMenu )
if( !_ContextVal || !_GroupMenu )
return;
CProperties propValidation = CProperties(_ContextVal->getValue16());
// botChatPrograms
uint32 availablePrograms = filterAvailablePrograms((uint32) _AvailablePrograms->getValue32());
CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
// Milko Pad
if ((_GroupMilkoPad != NULL) && (_GroupMilkoPad->getActive()))
{
if (canDisengage())
{
_MilkoAttackDisengage->setValue32(1);
if (_MilkoAttDisBut1)
_MilkoAttDisBut1->setHardText("uiMk_action5_1");
if (_MilkoAttDisBut2)
_MilkoAttDisBut2->setHardText("uiMk_action5_1");
}
else
{
_MilkoAttackDisengage->setValue32(0);
if (_MilkoAttDisBut1)
_MilkoAttDisBut1->setHardText("uiMk_action5_0");
if (_MilkoAttDisBut2)
_MilkoAttDisBut2->setHardText("uiMk_action5_0");
}
}
// Is the menu active
if(!_GroupMenu->getActive())
return;
updateContextMenuMissionsOptions( UserEntity->isRiding() );
updateContextMenuWebPage(availablePrograms);
updateContextMenuOutpostState(availablePrograms);
updateContextMenuOutpostBanish();
updateContextMenuMissionRing();
setupContextMenuCantTalk(); // can't talk by default
// If mode Combat (no talk, no give, no mount, no extract_rm)
if(UserEntity->isFighting())
{
// Loot
if(_TextLootAction)
_TextLootAction->setActive(false);
// Quartering
if(_TextQuartering)
_TextQuartering->setActive(false);
// Disable talk, unless with a player
if (ForceTalkWithBot) // tmp
{
updateContextMenuTalkEntries(availablePrograms);
}
else if (ForceTalkWithPlayer)
{
setupContextMenuTalkWithPlayer();
}
else
if(selection && selection->Type == CEntityCL::Player)
{
setupContextMenuTalkWithPlayer();
}
// Exchange
if(_TextExchange)
_TextExchange->setActive(false);
// Disable mount
if(_TextMount)
_TextMount->setActive(false);
// Disable FreeLook.
if(_TextFreeLook)
_TextFreeLook->setActive(false);
// Disable unseat.
if(_TextUnseat)
_TextUnseat->setActive(false);
// Disable extraction
if(_TextExtractRM)
_TextExtractRM->setActive(false);
}
// Mount
else if(UserEntity->isRiding())
{
// Loot
if(_TextLootAction)
_TextLootAction->setActive(false);
// Quartering
if(_TextQuartering)
_TextQuartering->setActive(false);
// No talk when riding
// No exchange when riding
if(_TextExchange)
_TextExchange->setActive(false);
// Disable mount
if(_TextMount)
_TextMount->setActive(false);
// Disable Free Look
if(_TextFreeLook)
_TextFreeLook->setActive(false);
// Enable unseat
if(_TextUnseat)
_TextUnseat->setActive(true);
// Disable extraction
if(_TextExtractRM)
_TextExtractRM->setActive(false);
}
// Not in combat or riding mode.
else
{
// Loot
if(_TextLootAction)
{
_TextLootAction->setActive(false);
// Action possible only if the client is not already busy and the selection is able to do this with you..
if(selection && selection->isDead() && (selection->properties().lootable() || selection->properties().liftable())
&& !R2::getEditor().isDMing()
)
_TextLootAction->setActive(true);
}
// Quartering
if(_TextQuartering)
{
_TextQuartering->setActive(false);
// Action possible only if the client is not already busy and the selection is able to do this with you..
if(selection && selection->isDead() && selection->properties().harvestable() && !R2::getEditor().isDMing())
_TextQuartering->setActive(true);
}
// talk ?
if (ForceTalkWithBot) // tmp
{
updateContextMenuTalkEntries(availablePrograms);
}
else if (ForceTalkWithPlayer)
{
setupContextMenuTalkWithPlayer();
}
else
if(UserEntity->selection() != UserEntity->slot()) // Talking again to yourself ?
{
if(selection)
{
if (selection->Type == CEntityCL::Player)
{
setupContextMenuTalkWithPlayer();
}
else
if(selection->properties().talkableTo())
{
if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
{
// Can talk with bot if not too far
CVectorD vect1 = selection->pos();
CVectorD vect2 = UserEntity->pos();
double distanceSquare = pow(vect1.x-vect2.x,2) + pow(vect1.y-vect2.y,2);
if (distanceSquare <= MaxTalkingDistSquare)
{
updateContextMenuTalkEntries(availablePrograms);
}
// Special case for buildings
if (distanceSquare <= MaxTalkingOutpostBuildingDistSquare)
_OkTextTradeOutpostBuilding = ((availablePrograms & (1 << BOTCHATTYPE::TradeOutpostBuilding)) != 0);
}
}
}
}
// Exchange
if(_TextExchange)
{
// Action possible only if the client is not already busy and the selection is able to do this with you..
if(selection && selection->properties().canExchangeItem())
_TextExchange->setActive(!UserEntity->isBusy());
else
_TextExchange->setActive(false);
}
// Enable Free Look
if(_TextFreeLook)
_TextFreeLook->setActive(true);
// Disable unseat
if(_TextUnseat)
_TextUnseat->setActive(false);
// Enable extraction for a forage source
if(_TextExtractRM)
{
_TextExtractRM->setActive(false);
if ( selection && selection->isForageSource() )
_TextExtractRM->setActive(true);
}
}
// Enable attack mode
if (_TextAttack)
_TextAttack->setActive(canAttack());
if (_TextDuel && _TextUnDuel)
{
if ((!UserEntity->isRiding()) && (_ServerInDuel->getValue8() != 0))
{
_TextDuel->setActive(false);
_TextUnDuel->setActive(true);
}
else if (canDuel())
{
_TextDuel->setActive(true);
_TextUnDuel->setActive(false);
}
else
{
_TextDuel->setActive(false);
_TextUnDuel->setActive(false);
}
}
if (_TextPvpChallenge && _TextUnPvpChallenge)
{
if ((!UserEntity->isRiding()) && (_ServerInPvpChallenge->getValue8() != 0))
{
_TextPvpChallenge->setActive(false);
_TextUnPvpChallenge->setActive(true);
}
else if (canPvpChallenge())
{
_TextPvpChallenge->setActive(true);
_TextUnPvpChallenge->setActive(false);
}
else
{
_TextPvpChallenge->setActive(false);
_TextUnPvpChallenge->setActive(false);
}
}
// Enable disengage mode
if (_TextDisengage)
_TextDisengage->setActive(canDisengage());
// Enable Autowalk
if(_TextMove)
_TextMove->setActive(!UserControls.autowalkState());
// Enable Stop Autowalk
if(_TextStop)
_TextStop->setActive(UserControls.autowalkState());
// Disable player properties
if(_TextInfo)
_TextInfo->setActive(selection && (!selection->isForageSource()));
// Follow
if(_TextFollow)
{
// Action possible only if the client is not already busy and the selection is able to do this with you..
_TextFollow->setActive(
selection &&
(! selection->slot() == UserEntity->slot()) &&
(!selection->isForageSource()) &&
(selection->isDead()==false) &&
(((availablePrograms & (1 << BOTCHATTYPE::DontFollow)) == 0)));
// See also below for mount/packer
}
// Assist
if(_TextAssist)
{
// Action possible only if the client is not already busy and the selection is able to do this with you..
_TextAssist->setActive(!R2::getEditor().isDMing() && selection && (! selection->slot() == UserEntity->slot()) && (!selection->isForageSource()) && (selection->isDead()==false));
// See also below for mount/packer
}
// Invite
if(_TextInvit)
{
bool invitable = false;
// User should not be flagged as invitable by himself, so no need to check that selection is not the user
if(selection && selection->properties().invitable() && propValidation.invitable() )
{
invitable = true;
}
// Grey/Ungrey the entry.
_TextInvit->setActive(invitable);
}
// Guild Invit
if(_TextGuildInvit)
{
// if server OK.
if(filterAvailablePrograms(_AvailablePrograms->getValue32())&(1 << BOTCHATTYPE::GuildInviteFlag))
_TextGuildInvit->setActive (true);
else
_TextGuildInvit->setActive (false);
}
// Active "Quit Team" if you are a member of one.
if(_TextQuitTeam)
{
if (_ServerTeamPresent)
{
_TextQuitTeam->setActive( _ServerTeamPresent->getValueBool() );
}
}
// Invite to friend list (only if target is a player, and not a friend already)
if(_TextAddToFriendList)
{
_TextAddToFriendList->setActive(false);
if (selection && selection->Type == CEntityCL::Player)
{
if (!selection->getEntityName().empty())
{
sint peopleIndex = PeopleInterraction.FriendList.getIndexFromName(selection->getEntityName());
if (peopleIndex == -1) // not already in friend list
{
_TextAddToFriendList->setActive(true);
}
}
}
}
// Pack/Mount Animal
if ( _TextMount )
_TextMount->setActive(false);
if(selection && (selection->isUserPackAnimal() || (selection->isUserMount())))
{
// Get the index of the selected animal, if owned by the player
sint animalIndex;
if ( ! selection->getPackAnimalIndexInDB( animalIndex ) )
animalIndex = -1;
// Disable 'Mount' if server says so
CViewTextMenu *pTextMount = NULL;
if ( propValidation.mountable() )
pTextMount = _TextMount;
else if (_TextMount)
_TextMount->setActive( false ); // pTextMount remains NULL
// Enable/disable various menu items
bool ok = testMenuOptionForPackAnimal( selection, animalIndex, true, _TextPAFollow, _TextPAStop, _TextPAFree,
_TextPAEnterStable, NULL /*no 'leave stable' in context menu*/, pTextMount,
NULL /*unmount always active in context menu when the character is riding*/);
// Follow & assist special case
if ( _TextFollow )
_TextFollow->setActive( false ); // can't follow own pet
if ( _TextAssist )
_TextAssist->setActive( false ); // can't assist a pet
// Write the selected pack animal, for future "beast_order" action handler
if(ok)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CCDBNodeLeaf *node= pIM->getDbProp("UI:GCM_BEAST_SELECTED", false);
// beast_order AH start with 1 (0 for ALL beasts)
if(node)
node->setValue32(animalIndex+1);
}
}
else
{
if (_TextPAFollow)
_TextPAFollow->setActive(false);
if (_TextPAStop)
_TextPAStop->setActive(false);
if (_TextPAFree)
_TextPAFree->setActive(false);
if (_TextPAEnterStable)
_TextPAEnterStable->setActive(false);
}
// build spire
if(_TextBuildTotem)
{
_TextBuildTotem->setActive(false);
if( availablePrograms & ( 1 << BOTCHATTYPE::Totem ) )
{
_TextBuildTotem->setActive(true);
}
}
// Apply real activation of Talk Texts.
applyTextTalk();
}
// ***************************************************************************
bool CGameContextMenu::canAttack()
{
if (R2::getEditor().isDMing()) return false;
bool ret = false;
CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
if (UserEntity->isFighting() || UserEntity->isRiding())
return ret;
// To enter in combat, the user should not be talking.
if(!CBotChatManager::getInstance()->getCurrPage()) // Not talking
{
// If there is a selection.
if (selection && selection->isDead() == false)
{
uint32 availablePrograms = (uint32) filterAvailablePrograms(_AvailablePrograms->getValue32());
if(selection->properties().attackable() || (availablePrograms & (1<<BOTCHATTYPE::Attackable)))
ret = true;
}
}
return ret;
}
// ***************************************************************************
bool CGameContextMenu::canDuel()
{
if (UserEntity->isFighting() || UserEntity->isRiding())
return false;
// To enter in combat, the user should not be talking.
if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
return false;
CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
if (selection == NULL)
return false;
if (selection->isPlayer())
if (selection->isDead() == false)
return true;
return false;
}
// ***************************************************************************
bool CGameContextMenu::canPvpChallenge()
{
if (UserEntity->isFighting() || UserEntity->isRiding())
return false;
// To enter in combat, the user should not be talking.
if(CBotChatManager::getInstance()->getCurrPage()) // Talking ?
return false;
CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
if (selection == NULL)
return false;
if (selection->isPlayer())
if (selection->isDead() == false)
return true;
return false;
}
// ***************************************************************************
bool CGameContextMenu::canDisengage()
{
if (UserEntity->isFighting())
return true;
else
return false;
}
// ***************************************************************************
bool CGameContextMenu::canTeamKick()
{
CEntityCL *selection = EntitiesMngr.entity(UserEntity->selection());
if (selection != NULL)
{
sint n = PeopleInterraction.TeamList.getIndexFromName(selection->getEntityName());
if (n >= 0)
return true;
}
return false;
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuMissionsOptions( bool forceHide )
{
for(uint k = 0; k < NUM_MISSION_OPTIONS; ++k)
{
CViewTextMenu *pVTM = _TextMission[k];
if (pVTM)
{
if ( _MissionOption[k] && (!forceHide) )
{
uint32 textID = (uint32) _MissionOption[k]->getValue32();
if (textID)
{
ucstring result;
bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID, result);
if (!res)
{
result = NLMISC::CI18N::get("uiMissionOptionNotReceived");
}
pVTM->setText(result);
pVTM->setActive(true);
}
else
{
pVTM->setText(ucstring(""));
pVTM->setActive(false);
}
}
else
{
pVTM->setText(ucstring(""));
pVTM->setActive(false);
}
}
}
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuWebPage(uint options)
{
// Show the web page (title must be present)
_OkTextWebPage= ((options & (1 << BOTCHATTYPE::WebPageFlag)) != 0);
if(_OkTextWebPage)
_OkTextWebPage= _WebPageTitle && _WebPageTitle->getValue32()!=0;
// Change the WebPage text, when available
CViewTextMenu *pVTM = _TextWebPage;
if (pVTM)
{
if ( _WebPageTitle )
{
uint32 textID = (uint32) _WebPageTitle->getValue32();
if (textID)
{
ucstring result;
bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textID, result);
if (!res)
{
result = NLMISC::CI18N::get("uiWebPageNameNotReceived");
}
pVTM->setText(result);
}
else
{
pVTM->setText(ucstring(""));
}
}
else
{
pVTM->setText(ucstring(""));
}
}
// apply the active
if (_TextWebPage) _TextWebPage->setActive(_OkTextWebPage);
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuOutpostState(uint options)
{
CSheetId outpostSheet;
// Outpost ok?
_OkTextOutpostState= false;
if ( (options & (1 << BOTCHATTYPE::OutpostFlag)) != 0 && _OutpostSheet)
{
// check that the outpost sheet is correct
outpostSheet= _OutpostSheet->getValue32();
CEntitySheet *s= SheetMngr.get(outpostSheet);
if(s && s->Type == CEntitySheet::OUTPOST)
_OkTextOutpostState= true;
}
// Fill the text
if(_OkTextOutpostState)
{
CViewTextMenu *pVTM = _TextOutpostState;
if (pVTM)
pVTM->setText(ucstring(STRING_MANAGER::CStringManagerClient::getOutpostLocalizedName(outpostSheet)));
}
// apply the active
if (_TextOutpostState) _TextOutpostState->setActive(_OkTextOutpostState);
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuOutpostBanish()
{
bool okForBanPlayer= false;
bool okForBanGuild= false;
// Test if the player can ban the targeted player / player's guild
extern void outpostTestUserCanBan(CCDBNodeLeaf *dbBanRight, bool &, bool &);
outpostTestUserCanBan(_OutpostRightToBannish, okForBanPlayer, okForBanGuild);
// validate text
if(_TextOutpostBanishPlayer) _TextOutpostBanishPlayer->setActive(okForBanPlayer);
if(_TextOutpostBanishGuild) _TextOutpostBanishGuild->setActive(okForBanGuild);
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuMissionRing()
{
for(uint k = 0; k < BOTCHATTYPE::MaxR2MissionEntryDatabase; ++k)
{
CViewTextMenu *pVTM = _TextMissionRing[k];
if (pVTM)
{
uint32 textId= 0;
if ( _MissionRing[k] )
textId= _MissionRing[k]->getValue32();
// if the textId is ok and Flag is set.
if ( textId )
{
ucstring result;
bool res = STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, result);
if (!res)
{
result = NLMISC::CI18N::get("uiMissionRingNameNotReceived");
}
pVTM->setText(result);
pVTM->setActive(true);
}
else
{
pVTM->setText(ucstring(""));
pVTM->setActive(false);
}
}
}
}
// ***************************************************************************
void CGameContextMenu::updateContextMenuTalkEntries(uint options)
{
if (ClientCfg.Local)
{
options = ~0; // in local mode, force all options to be shown (for debug)
}
// news
_OkTextNews= ((options & (1 << BOTCHATTYPE::NewsFlag)));
// trade
_OkTextTradeItem= ((options & (1 << BOTCHATTYPE::TradeItemFlag)) != 0);
_OkTextTradeTeleport= ((options & (1 << BOTCHATTYPE::TradeTeleportFlag)) != 0);
_OkTextTradeFaction= ((options & (1 << BOTCHATTYPE::TradeFactionFlag)) != 0);
_OkTextTradeCosmetic= ((options & (1 << BOTCHATTYPE::TradeCosmeticFlag)) != 0);
_OkTextTradeGuildOptions = ((options & (1 << BOTCHATTYPE::TradeBuildingOptions)) != 0);
_OkTextTradeOutpostBuilding = ((options & (1 << BOTCHATTYPE::TradeOutpostBuilding)) != 0);
_OkTextTradeGuildRoleMaster = ((options & (1 << BOTCHATTYPE::GuildRoleMaster)) != 0);
_OkTextTradePact= ((options & (1 << BOTCHATTYPE::TradePactFlag)) != 0);
_OkTextTradePhrase= ((options & (1 << BOTCHATTYPE::TradePhraseFlag)) != 0);
// choose mission
_OkTextChooseMission= ((options & (1 << BOTCHATTYPE::ChooseMissionFlag)) != 0);
// create guild
_OkTextCreateGuild= ((options & (1 << BOTCHATTYPE::CreateGuildFlag)) != 0);
// New Yoyo BotChat
_OkTextChooseZCCharge= ((options & (1 << BOTCHATTYPE::AskGuildDutyFlag)) != 0);
_OkTextCancelZCCharge= ((options & (1 << BOTCHATTYPE::CancelGuildDutyFlag)) != 0);
/*_OkTextBuyRM= ((options & (1 << BOTCHATTYPE::)) != 0);
_OkTextUpgradeRM= ((options & (1 << BOTCHATTYPE::)) != 0);
_OkTextDestroyBuilding= ((options & (1 << BOTCHATTYPE::)) != 0);*/
// TODO BOTCHAT: RM Buy/Upgrade.
// TODO BOTCHAT: Declare war no more through "Mission Option"
// TODO BOTCHAT: Destroy Building only if already created
// TODO BOTCHAT: ZCBuilder is deprecated, as is _OkTextChooseBuilding
// TODO BOTCHAT: _OkTextDynamicMission is deprecated
_OkTextDynamicMission= false;
_OkTextBuyRM= false;
_OkTextUpgradeRM= false;
_OkTextChooseBuilding= false;
_OkTextDestroyBuilding= _OkTextChooseBuilding;
}
// ***************************************************************************
void CGameContextMenu::setupContextMenuCantTalk()
{
updateContextMenuTalkEntries(0);
_OkTextTalk= false;
}
// ***************************************************************************
void CGameContextMenu::setupContextMenuTalkWithPlayer()
{
_OkTextTalk= true;
}
// ***************************************************************************
void CGameContextMenu::applyTextTalk()
{
if (_TextNews) _TextNews->setActive(_OkTextNews);
if (_TextTradeItem) _TextTradeItem->setActive(_OkTextTradeItem);
if (_TextTradeTeleport) _TextTradeTeleport->setActive(_OkTextTradeTeleport);
if (_TextTradeFaction) _TextTradeFaction->setActive(_OkTextTradeFaction);
if (_TextTradeCosmetic) _TextTradeCosmetic->setActive(_OkTextTradeCosmetic);
if (_TextTradeGuildOptions) _TextTradeGuildOptions->setActive(_OkTextTradeGuildOptions);
if (_TextTradeOutpostBuilding) _TextTradeOutpostBuilding->setActive(_OkTextTradeOutpostBuilding);
if (_TextTradeGuildRoleMaster) _TextTradeGuildRoleMaster->setActive(_OkTextTradeGuildRoleMaster);
if (_TextTradePact) _TextTradePact->setActive(_OkTextTradePact);
if (_TextTradePhrase) _TextTradePhrase->setActive(_OkTextTradePhrase);
if (_TextChooseMission) _TextChooseMission->setActive(_OkTextChooseMission);
if (_TextCreateGuild)
{
_TextCreateGuild->setActive(_OkTextCreateGuild);
// If the player is already in a guild set the text grayed
_TextCreateGuild->setGrayed(CGuildManager::getInstance()->isInGuild());
}
if (_TextDynamicMission) _TextDynamicMission->setActive(_OkTextDynamicMission);
if (_TextTalk) _TextTalk->setActive(_OkTextTalk);
if (_TextChooseZCCharge) _TextChooseZCCharge->setActive(_OkTextChooseZCCharge);
if (_TextChooseBuilding) _TextChooseBuilding->setActive(_OkTextChooseBuilding);
if (_TextBuyRM) _TextBuyRM->setActive(_OkTextBuyRM);
if (_TextUpgradeRM) _TextUpgradeRM->setActive(_OkTextUpgradeRM);
if (_TextCancelZCCharge) _TextCancelZCCharge->setActive(_OkTextCancelZCCharge);
if (_TextDestroyBuilding) _TextDestroyBuilding->setActive(_OkTextDestroyBuilding);
}
// ***************************************************************************
/**
* Enable/disable various menu items for animals.
* selectedAnimalInVision can be NULL (out of vision)
* index can be -1 (no owned animal)
* Any CViewTextMenu* can be NULL
*/
bool testMenuOptionForPackAnimal( CEntityCL* selectedAnimalInVision, uint index, bool clearAll,
CViewTextMenu *pFollow, CViewTextMenu *pStop, CViewTextMenu *pFree,
CViewTextMenu *pEnterStable, CViewTextMenu *pLeaveStable,
CViewTextMenu *pMount, CViewTextMenu *pUnmount )
{
if ( clearAll )
{
// Disable and gray all by default
if(pFollow) { pFollow->setActive(false); pFollow->setGrayed(true); }
if(pStop) { pStop->setActive(false); pStop->setGrayed(true); }
if(pFree) { pFree->setActive(false); pFree->setGrayed(true); }
if(pEnterStable) { pEnterStable->setActive(false); pEnterStable->setGrayed(true); }
if(pLeaveStable) { pLeaveStable->setActive(false); pLeaveStable->setGrayed(true); }
if(pMount) { pMount->setActive(false); pMount->setGrayed(true); }
if(pUnmount) { pUnmount->setActive(false); pUnmount->setGrayed(true); }
}
// Don't enable anything if index not found (e.g. the character is not the owner of the animal)
if ( (index == (uint)-1) || (!UserEntity) )
return false;
// Get animal status and type
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CCDBNodeLeaf *node= pIM->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS", index), false);
if(!node) return false;
ANIMAL_STATUS::EAnimalStatus status= (ANIMAL_STATUS::EAnimalStatus)node->getValue32();
node= pIM->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:TYPE", index), false);
if(!node) return false;
ANIMAL_TYPE::EAnimalType anitype= (ANIMAL_TYPE::EAnimalType)node->getValue32();
// COMMON PART FOR ALL TYPES OF ANIMAL
// Is the character mounted on the animal?
bool userIsMountedOnIt = false;
if ( selectedAnimalInVision && (anitype == ANIMAL_TYPE::Mount) && UserEntity->isRiding() )
{
uint8 mountSlot = (uint8)IngameDbMngr.getProp( "Entities:E" + toString(UserEntity->slot()) + ":P" + toString(CLFECOMMON::PROPERTY_ENTITY_MOUNTED_ID));
userIsMountedOnIt = (mountSlot == selectedAnimalInVision->slot());
}
bool onLandscape = ANIMAL_STATUS::isInLandscape(status);
double distanceSquare = 0;
if ( selectedAnimalInVision )
{
CVectorD vect1 = selectedAnimalInVision->pos();
CVectorD vect2 = UserEntity->pos();
distanceSquare = pow(vect1.x-vect2.x,2) + pow(vect1.y-vect2.y,2);
}
// Enable option only if pack animal present
if(ANIMAL_STATUS::isSpawned(status))
{
bool canEnterLeaveStable= ANIMAL_STATUS::canEnterLeaveStable(status);
if (!userIsMountedOnIt)
{
if(pFollow && onLandscape) pFollow->setActive(true);
if(pStop && onLandscape) pStop->setActive(true);
// Enter/leave stable are only displayed when near a stable ('canEnterLeaveStable')
if(pEnterStable && onLandscape && canEnterLeaveStable) pEnterStable->setActive(true);
if(pLeaveStable && ANIMAL_STATUS::isInStable(status) && canEnterLeaveStable) pLeaveStable->setActive(true);
// Can always free, dead/alive, in or out stable animals
if(pFree)
{
pFree->setActive(true);
pFree->setGrayed(false);
}
}
// If alive (and close to the character), ungray all
if(ANIMAL_STATUS::isAlive(status))
{
if (onLandscape && selectedAnimalInVision && (distanceSquare <= MaxAnimalCommandDistSquare))
{
if(pFollow) pFollow->setGrayed(false);
if(pStop) pStop->setGrayed(false);
if(pEnterStable) pEnterStable->setGrayed(false);
}
if(pLeaveStable) pLeaveStable->setGrayed(false);
}
}
// Specific part for mountable animal
if ((anitype == ANIMAL_TYPE::Mount) &&
(ANIMAL_STATUS::isSpawned(status)) && onLandscape)
{
if ( userIsMountedOnIt )
{
// Always allow to unmount the mounted mount
if(pUnmount) pUnmount->setActive(true);
if(pUnmount) pUnmount->setGrayed(false);
}
else
{
if(pMount &&
((!selectedAnimalInVision) || selectedAnimalInVision->properties().mountable()))
{
// Display 'Mount' if the entity is of mountable type
pMount->setActive(true);
// Enable 'Mount' if the character is not busy and the entity is alive and close enough
if(ANIMAL_STATUS::isAlive(status) && (!UserEntity->isRiding()) &&
(!UserEntity->isFighting()) && (!UserEntity->isBusy()))
{
if(selectedAnimalInVision && (distanceSquare <= MaxAnimalCommandDistSquare))
{
pMount->setGrayed(false);
}
}
}
}
}
return true;
}