/*
* The ManaPlus Client
* Copyright (C) 2004-2009 The Mana World Development Team
* Copyright (C) 2009-2010 The Mana Developers
* Copyright (C) 2011-2016 The ManaPlus Developers
*
* This file is part of The ManaPlus Client.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "gui/popups/popupmenu.h"
#include "actormanager.h"
#include "configuration.h"
#include "party.h"
#include "being/flooritem.h"
#include "being/localplayer.h"
#include "being/playerinfo.h"
#include "being/playerrelation.h"
#include "being/playerrelations.h"
#include "const/spells.h"
#include "enums/resources/map/mapitemtype.h"
#include "input/inputmanager.h"
#include "gui/buttontext.h"
#include "gui/gui.h"
#include "gui/viewport.h"
#include "gui/windowmenu.h"
#include "gui/windows/chatwindow.h"
#include "gui/windows/equipmentwindow.h"
#include "gui/windows/inventorywindow.h"
#include "gui/windows/minimap.h"
#include "gui/windows/ministatuswindow.h"
#include "gui/windows/npcdialog.h"
#include "gui/windows/outfitwindow.h"
#include "gui/windows/socialwindow.h"
#include "gui/windows/textcommandeditor.h"
#include "gui/windows/textdialog.h"
#include "gui/windows/tradewindow.h"
#include "gui/widgets/button.h"
#include "gui/widgets/createwidget.h"
#include "gui/widgets/progressbar.h"
#include "gui/widgets/scrollarea.h"
#include "gui/widgets/skillinfo.h"
#include "gui/widgets/textfield.h"
#include "gui/widgets/tabs/chat/whispertab.h"
#include "net/adminhandler.h"
#include "net/chathandler.h"
#include "net/guildhandler.h"
#ifdef EATHENA_SUPPORT
#include "net/homunculushandler.h"
#include "net/mercenaryhandler.h"
#include "net/npchandler.h"
#endif
#include "net/pethandler.h"
#include "net/serverfeatures.h"
#ifdef TMWA_SUPPORT
#include "net/tmwa/guildmanager.h"
#endif
#include "resources/chatobject.h"
#include "resources/iteminfo.h"
#include "resources/db/npcdb.h"
#include "resources/item/item.h"
#include "resources/map/map.h"
#include "resources/map/mapitem.h"
#include "resources/map/speciallayer.h"
#include "utils/copynpaste.h"
#include "utils/gettext.h"
#include "utils/process.h"
#include "debug.h"
std::string tradePartnerName;
PopupMenu *popupMenu = nullptr;
PopupMenu::PopupMenu() :
Popup("PopupMenu", "popupmenu.xml"),
mBrowserBox(new BrowserBox(this, BrowserBox::AUTO_SIZE, true,
"popupbrowserbox.xml")),
mScrollArea(nullptr),
mBeingId(BeingId_zero),
mFloorItemId(BeingId_zero),
mItemId(0),
mItemIndex(-1),
mItemColor(ItemColor_one),
mMapItem(nullptr),
mTab(nullptr),
mSpell(nullptr),
mWindow(nullptr),
mRenameListener(),
mPlayerListener(),
mDialog(nullptr),
mButton(nullptr),
mNick(),
mTextField(nullptr),
mType(ActorType::Unknown),
mX(0),
mY(0)
{
mBrowserBox->setOpaque(false);
mBrowserBox->setLinkHandler(this);
mRenameListener.setMapItem(nullptr);
mRenameListener.setDialog(nullptr);
mPlayerListener.setNick("");
mPlayerListener.setDialog(nullptr);
mPlayerListener.setType(ActorType::Unknown);
mScrollArea = new ScrollArea(this, mBrowserBox, false);
mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
}
void PopupMenu::postInit()
{
Popup::postInit();
add(mScrollArea);
}
void PopupMenu::showPopup(const int x, const int y, const Being *const being)
{
if (!being || !localPlayer || !actorManager)
return;
mBeingId = being->getId();
mNick = being->getName();
mType = being->getType();
mBrowserBox->clearRows();
mX = x;
mY = y;
const std::string &name = mNick;
mBrowserBox->addRow(name + being->getGenderSignWithSpace());
switch (being->getType())
{
case ActorType::Player:
{
// TRANSLATORS: popup menu item
// TRANSLATORS: trade with player
mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
// TRANSLATORS: popup menu item
// TRANSLATORS: trade attack player
mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
// TRANSLATORS: popup menu item
// TRANSLATORS: send whisper to player
mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
addGmCommands();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: heal player
mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
mBrowserBox->addRow("##3---");
addPlayerRelation(name);
mBrowserBox->addRow("##3---");
addFollow();
addPartyName(being->getPartyName());
const Guild *const guild1 = being->getGuild();
const Guild *const guild2 = localPlayer->getGuild();
if (guild2)
{
if (guild1)
{
if (guild1->getId() == guild2->getId())
{
mBrowserBox->addRow("/kickguild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: kick player from guild
_("Kick from guild"));
if (guild2->getServerGuild())
{
mBrowserBox->addRow(strprintf(
"@@guild-pos|%s >@@",
// TRANSLATORS: popup menu item
// TRANSLATORS: change player position in guild
_("Change pos in guild")));
}
}
}
else if (guild2->getMember(mNick))
{
mBrowserBox->addRow("/kickguild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: kick player from guild
_("Kick from guild"));
if (guild2->getServerGuild())
{
mBrowserBox->addRow(strprintf(
"@@guild-pos|%s >@@",
// TRANSLATORS: popup menu item
// TRANSLATORS: change player position in guild
_("Change pos in guild")));
}
}
else
{
#ifdef TMWA_SUPPORT
if (guild2->getServerGuild()
|| (guildManager && guildManager->havePower()))
#endif
{
mBrowserBox->addRow("/guild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: invite player to guild
_("Invite to guild"));
}
}
}
// TRANSLATORS: popup menu item
// TRANSLATORS: set player invisible for self by id
mBrowserBox->addRow("/nuke 'NAME'", _("Nuke"));
// TRANSLATORS: popup menu item
// TRANSLATORS: move to player location
mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
addPlayerMisc();
addBuySell(being);
#ifdef EATHENA_SUPPORT
addChat(being);
#endif
break;
}
case ActorType::Npc:
if (!addBeingMenu())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: talk with npc
mBrowserBox->addRow("/talk 'NAME'", _("Talk"));
if (serverFeatures->haveNpcWhispers())
{
mBrowserBox->addRow("/whispertext NPC:'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: whisper to npc
_("Whisper"));
}
// TRANSLATORS: popup menu item
// TRANSLATORS: buy from npc
mBrowserBox->addRow("/buy 'NAME'", _("Buy"));
// TRANSLATORS: popup menu item
// TRANSLATORS: sell to npc
mBrowserBox->addRow("/sell 'NAME'", _("Sell"));
}
addGmCommands();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: move to npc location
mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
// TRANSLATORS: popup menu item
// TRANSLATORS: add comment to npc
mBrowserBox->addRow("addcomment", _("Add comment"));
#ifdef EATHENA_SUPPORT
addChat(being);
#endif
break;
case ActorType::Monster:
{
// Monsters can be attacked
// TRANSLATORS: popup menu item
// TRANSLATORS: attack monster
mBrowserBox->addRow("/attack :'BEINGID'", _("Attack"));
addGmCommands();
mBrowserBox->addRow("##3---");
if (config.getBoolValue("enableAttackFilter"))
{
mBrowserBox->addRow("##3---");
if (actorManager->isInAttackList(name)
|| actorManager->isInIgnoreAttackList(name)
|| actorManager->isInPriorityAttackList(name))
{
mBrowserBox->addRow("/removeattack 'NAME'",
// TRANSLATORS: remove monster from attack list
// TRANSLATORS: popup menu item
_("Remove from attack list"));
}
else
{
mBrowserBox->addRow("/addpriorityattack 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: add monster to priotiry attack list
_("Add to priority attack list"));
mBrowserBox->addRow("/addattack 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: add monster to attack list
_("Add to attack list"));
mBrowserBox->addRow("/addignoreattack 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: add monster to ignore list
_("Add to ignore list"));
}
}
break;
}
#ifdef EATHENA_SUPPORT
case ActorType::Mercenary:
// TRANSLATORS: popup menu item
// TRANSLATORS: Mercenary move to master
mBrowserBox->addRow("mercenary to master", _("Move to master"));
addGmCommands();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: fire mercenary
mBrowserBox->addRow("fire mercenary", _("Fire"));
mBrowserBox->addRow("##3---");
break;
case ActorType::Homunculus:
// TRANSLATORS: popup menu item
// TRANSLATORS: Mercenary move to master
mBrowserBox->addRow("homunculus to master", _("Move to master"));
// TRANSLATORS: popup menu item
// TRANSLATORS: feed homunculus
mBrowserBox->addRow("homunculus feed", _("Feed"));
addGmCommands();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: delete homunculus
mBrowserBox->addRow("homunculus delete", _("Kill"));
mBrowserBox->addRow("##3---");
break;
case ActorType::Pet:
if (being->getOwner() == localPlayer)
{
// TRANSLATORS: popup menu item
// TRANSLATORS: feed pet
mBrowserBox->addRow("pet feed", _("Feed"));
// TRANSLATORS: popup menu item
// TRANSLATORS: pet drop loot
mBrowserBox->addRow("pet drop loot", _("Drop loot"));
// TRANSLATORS: popup menu item
// TRANSLATORS: pet unequip item
mBrowserBox->addRow("pet unequip", _("Unequip"));
addGmCommands();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: pet rename item
mBrowserBox->addRow("/setpetname", _("Rename"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: pet return to egg
mBrowserBox->addRow("pet to egg", _("Return to egg"));
mBrowserBox->addRow("##3---");
}
break;
case ActorType::SkillUnit:
// +++ need impliment menu
break;
#endif
case ActorType::Avatar:
case ActorType::Unknown:
case ActorType::FloorItem:
case ActorType::Portal:
case ActorType::LocalPet:
default:
break;
}
// TRANSLATORS: popup menu item
// TRANSLATORS: add being name to chat
mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
bool PopupMenu::addBeingMenu()
{
Being *being = actorManager->findBeing(mBeingId);
if (!being)
return false;
BeingInfo *const info = NPCDB::get(fromInt(
being->getSubType(), BeingTypeId));
if (!info)
return false;
const std::vector &menu = info->getMenu();
FOR_EACH (std::vector::const_iterator, it, menu)
{
const BeingMenuItem &item = *it;
mBrowserBox->addRow("/" + item.command, item.name.c_str());
}
return true;
}
void PopupMenu::setMousePos()
{
if (viewport)
{
mX = viewport->mMouseX;
mY = viewport->mMouseY;
}
else
{
Gui::getMouseState(mX, mY);
}
}
void PopupMenu::showPopup(const int x, const int y,
const std::vector &beings)
{
mX = x;
mY = y;
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Players"));
FOR_EACH (std::vector::const_iterator, it, beings)
{
const Being *const being = dynamic_cast(*it);
const ActorSprite *const actor = *it;
if (being && !being->getName().empty())
{
mBrowserBox->addRow(strprintf("@@player_%u|%s >@@",
CAST_U32(being->getId()), (being->getName()
+ being->getGenderSignWithSpace()).c_str()));
}
else if (actor->getType() == ActorType::FloorItem)
{
const FloorItem *const floorItem
= static_cast(actor);
mBrowserBox->addRow(strprintf("@@flooritem_%u|%s >@@",
CAST_U32(actor->getId()),
floorItem->getName().c_str()));
}
}
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showPlayerPopup(const std::string &nick)
{
if (nick.empty() || !localPlayer)
return;
setMousePos();
mNick = nick;
mBeingId = BeingId_zero;
mType = ActorType::Player;
mBrowserBox->clearRows();
const std::string &name = mNick;
mBrowserBox->addRow(name);
// TRANSLATORS: popup menu item
// TRANSLATORS: send whisper to player
mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
addGmCommands();
mBrowserBox->addRow("##3---");
addPlayerRelation(name);
mBrowserBox->addRow("##3---");
addFollow();
// TRANSLATORS: popup menu item
// TRANSLATORS: add comment to player
mBrowserBox->addRow("addcomment", _("Add comment"));
if (localPlayer->isInParty())
{
const Party *const party = localPlayer->getParty();
if (party)
{
const PartyMember *const member = party->getMember(mNick);
if (member)
{
// TRANSLATORS: popup menu item
// TRANSLATORS: kick player from party
mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
mBrowserBox->addRow("##3---");
const PartyMember *const o = party->getMember(
localPlayer->getName());
if (o && member->getMap() == o->getMap())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: move to player position
mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
}
}
}
}
const Guild *const guild2 = localPlayer->getGuild();
if (guild2)
{
if (guild2->getMember(mNick))
{
#ifdef TMWA_SUPPORT
if (guild2->getServerGuild() || (guildManager
&& guildManager->havePower()))
#endif
{
mBrowserBox->addRow("/kickguild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: kick player from guild
_("Kick from guild"));
}
if (guild2->getServerGuild())
{
mBrowserBox->addRow(strprintf(
// TRANSLATORS: popup menu item
// TRANSLATORS: change player position in guild
"@@guild-pos|%s >@@", _("Change pos in guild")));
}
}
else
{
#ifdef TMWA_SUPPORT
if (guild2->getServerGuild() || (guildManager
&& guildManager->havePower()))
#endif
{
// TRANSLATORS: popup menu item
// TRANSLATORS: invite player to guild
mBrowserBox->addRow("/guild 'NAME'", _("Invite to guild"));
}
}
}
addBuySellDefault();
// TRANSLATORS: popup menu item
// TRANSLATORS: add player name to chat
mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(mX, mY);
}
void PopupMenu::showPopup(const int x, const int y,
const FloorItem *const floorItem)
{
if (!floorItem)
return;
mX = x;
mY = y;
mFloorItemId = floorItem->getId();
mType = ActorType::FloorItem;
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = floorItem->getCard(f);
mBrowserBox->clearRows();
const std::string name = floorItem->getName();
mNick = name;
mBrowserBox->addRow(name);
if (config.getBoolValue("enablePickupFilter"))
{
if (actorManager->isInPickupList(name)
|| (actorManager->isInPickupList("")
&& !actorManager->isInIgnorePickupList(name)))
{
// TRANSLATORS: popup menu item
// TRANSLATORS: pickup item from ground
mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
mBrowserBox->addRow("##3---");
}
addPickupFilter(name);
}
else
{
// TRANSLATORS: popup menu item
// TRANSLATORS: pickup item from ground
mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
}
addProtection();
// TRANSLATORS: popup menu item
// TRANSLATORS: add item name to chat
mBrowserBox->addRow("/addchat 'FLOORID''CARDS'", _("Add to chat"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(mX, mY);
}
void PopupMenu::showPopup(const int x, const int y, MapItem *const mapItem)
{
if (!mapItem)
return;
mMapItem = mapItem;
mX = x;
mY = y;
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Map Item"));
// TRANSLATORS: popup menu item
// TRANSLATORS: rename map item
mBrowserBox->addRow("rename map", _("Rename"));
// TRANSLATORS: popup menu item
// TRANSLATORS: remove map item
mBrowserBox->addRow("remove map", _("Remove"));
if (localPlayer && localPlayer->isGM())
{
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: warp to map item
mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
}
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showMapPopup(const int x, const int y,
const int x2, const int y2,
const bool isMinimap)
{
mX = x2;
mY = y2;
if (isMinimap)
mWindow = minimap;
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Map Item"));
if (localPlayer && localPlayer->isGM())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: warp to map item
mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
}
// TRANSLATORS: popup menu item
// TRANSLATORS: move to map item
mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
// TRANSLATORS: popup menu item
// TRANSLATORS: move camera to map item
mBrowserBox->addRow("/movecamera 'X' 'Y'", _("Move camera"));
mBrowserBox->addRow("##3---");
if (isMinimap)
{
// TRANSLATORS: popup menu item
mBrowserBox->addRow("window close", _("Close"));
}
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showOutfitsWindowPopup(const int x, const int y)
{
mX = x;
mY = y;
mWindow = outfitWindow;
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Outfits"));
// TRANSLATORS: popup menu item
// TRANSLATORS: clear selected outfit
mBrowserBox->addRow("clear outfit", _("Clear outfit"));
mBrowserBox->addRow("##3---");
addWindowMenu(outfitWindow);
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showSpellPopup(const int x, const int y,
TextCommand *const cmd)
{
if (!cmd)
return;
mBrowserBox->clearRows();
mSpell = cmd;
mX = x;
mY = y;
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Spells"));
// TRANSLATORS: popup menu item
// TRANSLATORS: edit selected spell
mBrowserBox->addRow("edit spell", _("Edit spell"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showChatPopup(const int x, const int y, ChatTab *const tab)
{
if (!tab || !actorManager || !localPlayer)
return;
mTab = tab;
mX = x;
mY = y;
mWindow = chatWindow;
mBrowserBox->clearRows();
const ChatTabType::Type &type = tab->getType();
if (type == ChatTabType::WHISPER || type == ChatTabType::CHANNEL)
{
// TRANSLATORS: popup menu item
// TRANSLATORS: close chat tab
mBrowserBox->addRow("chat close", _("Close"));
}
// TRANSLATORS: popup menu item
// TRANSLATORS: remove all text from chat tab
mBrowserBox->addRow("/chatclear", _("Clear"));
mBrowserBox->addRow("##3---");
if (tab->getAllowHighlight())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: disable chat tab highlight
mBrowserBox->addRow("disable highlight", _("Disable highlight"));
}
else
{
// TRANSLATORS: popup menu item
// TRANSLATORS: enable chat tab highlight
mBrowserBox->addRow("enable highlight", _("Enable highlight"));
}
if (tab->getRemoveNames())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: do not remove player names from chat tab
mBrowserBox->addRow("dont remove name", _("Don't remove name"));
}
else
{
// TRANSLATORS: popup menu item
// TRANSLATORS: remove player names from chat tab
mBrowserBox->addRow("remove name", _("Remove name"));
}
if (tab->getNoAway())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: enable away messages in chat tab
mBrowserBox->addRow("enable away", _("Enable away"));
}
else
{
// TRANSLATORS: popup menu item
// TRANSLATORS: disable away messages in chat tab
mBrowserBox->addRow("disable away", _("Disable away"));
}
mBrowserBox->addRow("##3---");
if (tab->getType() == CAST_S32(ChatTabType::PARTY))
{
// TRANSLATORS: popup menu item
// TRANSLATORS: enable away messages in chat tab
mBrowserBox->addRow("/leaveparty", _("Leave"));
mBrowserBox->addRow("##3---");
}
// TRANSLATORS: popup menu item
// TRANSLATORS: copy selected text to clipboard
mBrowserBox->addRow("/chatclipboard 'X' 'Y'", _("Copy to clipboard"));
mBrowserBox->addRow("##3---");
if (type == ChatTabType::WHISPER)
{
const WhisperTab *const wTab = static_cast(tab);
std::string name = wTab->getNick();
const Being* const being = actorManager->findBeingByName(
name, ActorType::Player);
addGmCommands();
if (being)
{
mBeingId = being->getId();
mNick = being->getName();
mType = being->getType();
// TRANSLATORS: popup menu item
// TRANSLATORS: trade with player
mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
// TRANSLATORS: popup menu item
// TRANSLATORS: attack player
mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: heal player
mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
mBrowserBox->addRow("##3---");
addPlayerRelation(name);
mBrowserBox->addRow("##3---");
addFollow();
// TRANSLATORS: popup menu item
// TRANSLATORS: move to player position
mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
addPlayerMisc();
addBuySell(being);
mBrowserBox->addRow("##3---");
addParty(wTab->getNick());
const Guild *const guild1 = being->getGuild();
const Guild *const guild2 = localPlayer->getGuild();
if (guild2)
{
if (guild1)
{
if (guild1->getId() == guild2->getId())
{
#ifdef TMWA_SUPPORT
if (guild2->getServerGuild() || (guildManager
&& guildManager->havePower()))
#endif
{
mBrowserBox->addRow("/kickguild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: kick player from guild
_("Kick from guild"));
}
if (guild2->getServerGuild())
{
mBrowserBox->addRow(strprintf("@@guild-pos|%s >@@",
// TRANSLATORS: popup menu item
// TRANSLATORS: change player position in guild
_("Change pos in guild")));
}
}
}
else
{
#ifdef TMWA_SUPPORT
if (guild2->getServerGuild() || (guildManager
&& guildManager->havePower()))
#endif
{
mBrowserBox->addRow("/guild 'NAME'",
// TRANSLATORS: popup menu item
// TRANSLATORS: invite player to guild
_("Invite to guild"));
}
}
}
}
else
{
mBeingId = BeingId_zero;
mNick = name;
mType = ActorType::Player;
addPlayerRelation(name);
mBrowserBox->addRow("##3---");
addFollow();
if (localPlayer->isInParty())
{
const Party *const party = localPlayer->getParty();
if (party)
{
const PartyMember *const m = party->getMember(mNick);
if (m)
{
// TRANSLATORS: popup menu item
// TRANSLATORS: move to player location
mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
}
}
}
addPlayerMisc();
addBuySellDefault();
if (serverFeatures->havePartyNickInvite())
addParty(wTab->getNick());
mBrowserBox->addRow("##3---");
}
}
addWindowMenu(chatWindow);
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showChangePos(const int x, const int y)
{
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("Change guild position"));
if (!localPlayer)
return;
mX = x;
mY = y;
const Guild *const guild = localPlayer->getGuild();
if (guild)
{
const PositionsMap &map = guild->getPositions();
FOR_EACH (PositionsMap::const_iterator, itr, map)
{
mBrowserBox->addRow(strprintf("@@guild-pos-%u|%s@@",
itr->first, itr->second.c_str()));
}
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
else
{
mBeingId = BeingId_zero;
mFloorItemId = BeingId_zero;
mItemIndex = -1;
mItemId = 0;
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = 0;
mMapItem = nullptr;
mNick.clear();
mType = ActorType::Unknown;
mX = 0;
mY = 0;
setVisible(Visible_false);
}
}
void PopupMenu::showWindowPopup(Window *const window)
{
if (!window)
return;
setMousePos();
mWindow = window;
mBrowserBox->clearRows();
// TRANSLATORS: popup menu header
mBrowserBox->addRow(_("window"));
addWindowMenu(window);
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(mX, mY);
}
void PopupMenu::addWindowMenu(const Window *const window)
{
if (!window)
return;
if (window->getAlowClose())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: close window
mBrowserBox->addRow("window close", _("Close"));
}
if (window->isStickyButtonLock())
{
if (window->isSticky())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: unlock window
mBrowserBox->addRow("window unlock", _("Unlock"));
}
else
{
// TRANSLATORS: popup menu item
// TRANSLATORS: lock window
mBrowserBox->addRow("window lock", _("Lock"));
}
}
}
void PopupMenu::handleLink(const std::string &link,
MouseEvent *event A_UNUSED)
{
Being *being = nullptr;
if (actorManager)
being = actorManager->findBeing(mBeingId);
if (link == "chat close" && mTab)
{
inputManager.executeChatCommand(InputAction::CLOSE_CHAT_TAB,
std::string(), mTab);
}
else if (link == "remove map" && mMapItem)
{
if (viewport)
{
const Map *const map = viewport->getMap();
if (map)
{
SpecialLayer *const specialLayer = map->getSpecialLayer();
if (specialLayer)
{
const bool isHome = (mMapItem->getType()
== CAST_S32(MapItemType::HOME));
const int x = static_cast(mMapItem->getX());
const int y = static_cast(mMapItem->getY());
specialLayer->setTile(x, y,
CAST_S32(MapItemType::EMPTY));
if (socialWindow)
socialWindow->removePortal(x, y);
if (isHome && localPlayer)
{
localPlayer->removeHome();
localPlayer->saveHomes();
}
}
}
}
}
else if (link == "rename map" && mMapItem)
{
mRenameListener.setMapItem(mMapItem);
CREATEWIDGETV(mDialog, TextDialog,
// TRANSLATORS: dialog caption
// TRANSLATORS: number of chars in string should be near original
_("Rename map sign "),
// TRANSLATORS: label
// TRANSLATORS: number of chars in string should be near original
_("Name: "));
mRenameListener.setDialog(mDialog);
mDialog->setText(mMapItem->getComment());
mDialog->setActionEventId("ok");
mDialog->addActionListener(&mRenameListener);
}
else if (link == "edit spell" && mSpell)
{
CREATEWIDGET(TextCommandEditor, mSpell);
}
else if (link == "addcomment" && !mNick.empty())
{
TextDialog *const dialog = CREATEWIDGETR(TextDialog,
// TRANSLATORS: dialog caption
// TRANSLATORS: number of chars in string should be near original
_("Player comment "),
// TRANSLATORS: label
// TRANSLATORS: number of chars in string should be near original
_("Comment: "));
mPlayerListener.setDialog(dialog);
mPlayerListener.setNick(mNick);
mPlayerListener.setType(mType);
if (being)
{
being->updateComment();
dialog->setText(being->getComment());
}
else
{
dialog->setText(Being::loadComment(mNick,
static_cast(mType)));
}
dialog->setActionEventId("ok");
dialog->addActionListener(&mPlayerListener);
}
else if (link == "enable highlight" && mTab)
{
inputManager.executeChatCommand(InputAction::ENABLE_HIGHLIGHT,
std::string(), mTab);
}
else if (link == "disable highlight" && mTab)
{
inputManager.executeChatCommand(InputAction::DISABLE_HIGHLIGHT,
std::string(), mTab);
}
else if (link == "dont remove name" && mTab)
{
inputManager.executeChatCommand(InputAction::DONT_REMOVE_NAME,
std::string(), mTab);
}
else if (link == "remove name" && mTab)
{
inputManager.executeChatCommand(InputAction::REMOVE_NAME,
std::string(), mTab);
}
else if (link == "disable away" && mTab)
{
inputManager.executeChatCommand(InputAction::DISABLE_AWAY,
std::string(), mTab);
}
else if (link == "enable away" && mTab)
{
inputManager.executeChatCommand(InputAction::ENABLE_AWAY,
std::string(), mTab);
}
else if (link == "attack moveup")
{
if (actorManager)
{
const int idx = actorManager->getAttackMobIndex(mNick);
if (idx > 0)
{
std::list mobs
= actorManager->getAttackMobs();
std::list::iterator it = mobs.begin();
std::list::iterator it2 = it;
while (it != mobs.end())
{
if (*it == mNick)
{
-- it2;
mobs.splice(it2, mobs, it);
actorManager->setAttackMobs(mobs);
actorManager->rebuildAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow)
socialWindow->updateAttackFilter();
}
}
}
else if (link == "priority moveup")
{
if (actorManager)
{
const int idx = actorManager->
getPriorityAttackMobIndex(mNick);
if (idx > 0)
{
std::list mobs
= actorManager->getPriorityAttackMobs();
std::list::iterator it = mobs.begin();
std::list::iterator it2 = it;
while (it != mobs.end())
{
if (*it == mNick)
{
-- it2;
mobs.splice(it2, mobs, it);
actorManager->setPriorityAttackMobs(mobs);
actorManager->rebuildPriorityAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow)
socialWindow->updateAttackFilter();
}
}
}
else if (link == "attack movedown")
{
if (actorManager)
{
const int idx = actorManager->getAttackMobIndex(mNick);
const int size = actorManager->getAttackMobsSize();
if (idx + 1 < size)
{
std::list mobs
= actorManager->getAttackMobs();
std::list::iterator it = mobs.begin();
std::list::iterator it2 = it;
while (it != mobs.end())
{
if (*it == mNick)
{
++ it2;
if (it2 == mobs.end())
break;
mobs.splice(it, mobs, it2);
actorManager->setAttackMobs(mobs);
actorManager->rebuildAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow)
socialWindow->updateAttackFilter();
}
}
}
else if (link == "priority movedown")
{
if (localPlayer && actorManager)
{
const int idx = actorManager
->getPriorityAttackMobIndex(mNick);
const int size = actorManager->getPriorityAttackMobsSize();
if (idx + 1 < size)
{
std::list mobs
= actorManager->getPriorityAttackMobs();
std::list::iterator it = mobs.begin();
std::list::iterator it2 = it;
while (it != mobs.end())
{
if (*it == mNick)
{
++ it2;
if (it2 == mobs.end())
break;
mobs.splice(it, mobs, it2);
actorManager->setPriorityAttackMobs(mobs);
actorManager->rebuildPriorityAttackMobs();
break;
}
++ it;
++ it2;
}
if (socialWindow)
socialWindow->updateAttackFilter();
}
}
}
else if (link == "items" && being)
{
if (being == localPlayer)
{
if (equipmentWindow && !equipmentWindow->isWindowVisible())
equipmentWindow->setVisible(Visible_true);
}
else
{
if (beingEquipmentWindow)
{
beingEquipmentWindow->setBeing(being);
beingEquipmentWindow->setVisible(Visible_true);
}
}
}
else if (link == "undress item" && being && mItemId)
{
being->undressItemById(mItemId);
}
else if (link == "guild-pos" && !mNick.empty())
{
showChangePos(getX(), getY());
return;
}
else if (link == "clear outfit")
{
if (outfitWindow)
outfitWindow->clearCurrentOutfit();
}
else if (link == "clipboard copy")
{
if (mTextField)
mTextField->handleCopy();
}
else if (link == "clipboard paste")
{
if (mTextField)
mTextField->handlePaste();
}
else if (link == "open link" && !mNick.empty())
{
openBrowser(mNick);
}
else if (link == "clipboard link" && !mNick.empty())
{
sendBuffer(mNick);
}
else if (link == "goto" && !mNick.empty())
{
adminHandler->gotoName(mNick);
}
else if (link == "recall" && !mNick.empty())
{
adminHandler->recallName(mNick);
}
else if (link == "revive" && !mNick.empty())
{
adminHandler->reviveName(mNick);
}
else if (link == "ipcheck" && !mNick.empty())
{
adminHandler->ipcheckName(mNick);
}
else if (link == "gm" && !mNick.empty())
{
showGMPopup();
return;
}
else if (link == "window close" && mWindow)
{
if (Widget::widgetExists(mWindow))
mWindow->close();
}
else if (link == "window unlock" && mWindow)
{
if (Widget::widgetExists(mWindow))
mWindow->setSticky(false);
}
else if (link == "window lock" && mWindow)
{
if (Widget::widgetExists(mWindow))
mWindow->setSticky(true);
}
#ifdef EATHENA_SUPPORT
else if (link == "join chat" && being)
{
const ChatObject *const chat = being->getChat();
if (chat)
chatHandler->joinChat(chat, "");
}
else if (link == "fire mercenary")
{
mercenaryHandler->fire();
}
else if (link == "mercenary to master")
{
mercenaryHandler->moveToMaster();
}
else if (link == "homunculus to master")
{
homunculusHandler->moveToMaster();
}
else if (link == "homunculus feed")
{
homunculusHandler->feed();
}
else if (link == "homunculus delete")
{
homunculusHandler->fire();
}
else if (link == "craftmenu")
{
showCraftPopup();
return;
}
#endif
else if (link == "pet feed")
{
petHandler->feed();
}
else if (link == "pet drop loot")
{
petHandler->dropLoot();
}
else if (link == "pet to egg")
{
petHandler->returnToEgg();
}
else if (link == "pet unequip")
{
petHandler->unequip();
}
else if (!link.compare(0, 10, "guild-pos-"))
{
if (localPlayer)
{
const int num = atoi(link.substr(10).c_str());
const Guild *const guild = localPlayer->getGuild();
if (guild)
{
guildHandler->changeMemberPostion(
guild->getMember(mNick), num);
}
}
}
else if (!link.compare(0, 7, "player_"))
{
if (actorManager)
{
mBeingId = fromInt(atoi(link.substr(7).c_str()), BeingId);
being = actorManager->findBeing(mBeingId);
if (being)
{
showPopup(getX(), getY(), being);
return;
}
}
}
else if (!link.compare(0, 10, "flooritem_"))
{
if (actorManager)
{
const BeingId id = fromInt(atoi(
link.substr(10).c_str()), BeingId);
if (id != BeingId_zero)
{
const FloorItem *const item = actorManager->findItem(id);
if (item)
{
mFloorItemId = item->getId();
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = item->getCard(f);
showPopup(getX(), getY(), item);
return;
}
}
}
}
else if (!link.compare(0, 12, "hide button_"))
{
if (windowMenu)
windowMenu->showButton(link.substr(12), Visible_false);
}
else if (!link.compare(0, 12, "show button_"))
{
if (windowMenu)
windowMenu->showButton(link.substr(12), Visible_true);
}
else if (!link.compare(0, 9, "hide bar_"))
{
if (miniStatusWindow)
miniStatusWindow->showBar(link.substr(9), Visible_false);
}
else if (!link.compare(0, 9, "show bar_"))
{
if (miniStatusWindow)
miniStatusWindow->showBar(link.substr(9), Visible_true);
}
else if (!link.compare(0, 12, "show window_"))
{
const int id = atoi(link.substr(12).c_str());
if (id >= 0)
inputManager.executeAction(static_cast(id));
}
else if (!link.compare(0, 6, "mute_+"))
{
if (being)
{
const int time = atoi(link.substr(6).c_str());
adminHandler->mute(being, 1, time);
}
}
else if (!link.compare(0, 6, "mute_-"))
{
if (being)
{
const int time = atoi(link.substr(6).c_str());
adminHandler->mute(being, 0, time);
}
}
else if (!link.empty() && link[0] == '/')
{
std::string cmd = link.substr(1);
replaceAll(cmd, "'NAME'", mNick);
replaceAll(cmd, "'X'", toString(mX));
replaceAll(cmd, "'Y'", toString(mY));
replaceAll(cmd, "'BEINGID'", toString(toInt(mBeingId, int)));
replaceAll(cmd, "'FLOORID'", toString(toInt(mFloorItemId, int)));
replaceAll(cmd, "'ITEMID'", toString(mItemId));
replaceAll(cmd, "'ITEMCOLOR'", toString(toInt(mItemColor, int)));
replaceAll(cmd, "'BEINGTYPEID'", toString(CAST_S32(mType)));
replaceAll(cmd, "'PLAYER'", localPlayer->getName());
if (mItemIndex >= 0)
replaceAll(cmd, "'INVINDEX'", toString(mItemIndex));
else
replaceAll(cmd, "'INVINDEX'", "0");
if (mMapItem)
{
replaceAll(cmd, "'MAPX'", toString(mMapItem->getX()));
replaceAll(cmd, "'MAPY'", toString(mMapItem->getY()));
}
else
{
replaceAll(cmd, "'MAPX'", toString(mX));
replaceAll(cmd, "'MAPY'", toString(mY));
}
std::string cards;
for (int f = 0; f < maxCards; f ++)
{
const int id = mItemCards[f];
if (id)
{
cards.append(",");
cards.append(toString(id));
}
}
replaceAll(cmd, "'CARDS'", cards);
const size_t pos = cmd.find(' ');
const std::string type(cmd, 0, pos);
std::string args(cmd, pos == std::string::npos ? cmd.size() : pos + 1);
args = trim(args);
inputManager.executeChatCommand(type, args, mTab);
}
// Unknown actions
else if (link != "cancel")
{
logger->log("PopupMenu: Warning, unknown action '%s'", link.c_str());
}
setVisible(Visible_false);
mBeingId = BeingId_zero;
mFloorItemId = BeingId_zero;
mItemId = 0;
mItemIndex = -1;
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = 0;
mItemColor = ItemColor_one;
mMapItem = nullptr;
mTab = nullptr;
mSpell = nullptr;
mWindow = nullptr;
mDialog = nullptr;
mButton = nullptr;
mNick.clear();
mTextField = nullptr;
mType = ActorType::Unknown;
mX = 0;
mY = 0;
}
void PopupMenu::showPopup(Window *const parent,
const int x, const int y,
const Item *const item,
const InventoryTypeT type)
{
if (!item)
return;
mItemId = item->getId();
mItemIndex = item->getInvIndex();
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = item->getCard(f);
mItemColor = item->getColor();
mWindow = parent;
mX = x;
mY = y;
mNick.clear();
mBrowserBox->clearRows();
const int cnt = item->getQuantity();
const bool isProtected = PlayerInfo::isItemProtected(mItemId);
switch (type)
{
case InventoryType::Inventory:
if (tradeWindow && tradeWindow->isWindowVisible() && !isProtected)
{
// TRANSLATORS: popup menu item
// TRANSLATORS: add item to trade
mBrowserBox->addRow("/addtrade 'INVINDEX'", _("Add to trade"));
if (cnt > 1)
{
if (cnt > 10)
{
mBrowserBox->addRow("/addtrade 'INVINDEX' 10",
// TRANSLATORS: popup menu item
// TRANSLATORS: add 10 item amount to trade
_("Add to trade 10"));
}
mBrowserBox->addRow("/addtrade 'INVINDEX' /",
// TRANSLATORS: popup menu item
// TRANSLATORS: add half item amount to trade
_("Add to trade half"));
mBrowserBox->addRow("/addtrade 'INVINDEX' -1",
// TRANSLATORS: popup menu item
// TRANSLATORS: add all amount except one item to trade
_("Add to trade all-1"));
mBrowserBox->addRow("/addtrade 'INVINDEX' all",
// TRANSLATORS: popup menu item
// TRANSLATORS: add all amount item to trade
_("Add to trade all"));
}
mBrowserBox->addRow("##3---");
}
if (InventoryWindow::isStorageActive())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: add item to storage
mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
if (cnt > 1)
{
if (cnt > 10)
{
mBrowserBox->addRow("/invtostorage 'INVINDEX' 10",
// TRANSLATORS: popup menu item
// TRANSLATORS: add 10 item amount to storage
_("Store 10"));
}
mBrowserBox->addRow("/invtostorage 'INVINDEX' /",
// TRANSLATORS: popup menu item
// TRANSLATORS: add half item amount to storage
_("Store half"));
mBrowserBox->addRow("/invtostorage 'INVINDEX' -1",
// TRANSLATORS: popup menu item
// TRANSLATORS: add all except one item to storage
_("Store all-1"));
mBrowserBox->addRow("/invtostorage 'INVINDEX' all",
// TRANSLATORS: popup menu item
// TRANSLATORS: add all item amount to storage
_("Store all"));
}
mBrowserBox->addRow("##3---");
}
#ifdef EATHENA_SUPPORT
if (npcHandler)
{
NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
if (dialog &&
dialog->getInputState() == NpcDialog::NPC_INPUT_ITEM_CRAFT)
{
mBrowserBox->addRow("craftmenu",
// TRANSLATORS: popup menu item
// TRANSLATORS: sub menu for craft
_("Move to craft..."));
}
}
#endif
addUseDrop(item, isProtected);
break;
case InventoryType::Storage:
// TRANSLATORS: popup menu item
// TRANSLATORS: get item from storage
mBrowserBox->addRow("/storagetoinv 'INVINDEX'", _("Retrieve"));
if (cnt > 1)
{
if (cnt > 10)
{
mBrowserBox->addRow("/storagetoinv 'INVINDEX' 10",
// TRANSLATORS: popup menu item
// TRANSLATORS: get 10 item amount from storage
_("Retrieve 10"));
}
mBrowserBox->addRow("/storagetoinv 'INVINDEX' /",
// TRANSLATORS: popup menu item
// TRANSLATORS: get half item amount from storage
_("Retrieve half"));
mBrowserBox->addRow("/storagetoinv 'INVINDEX' -1",
// TRANSLATORS: popup menu item
// TRANSLATORS: get all except one item amount from storage
_("Retrieve all-1"));
mBrowserBox->addRow("/storagetoinv 'INVINDEX' all",
// TRANSLATORS: popup menu item
// TRANSLATORS: get all item amount from storage
_("Retrieve all"));
}
break;
case InventoryType::Trade:
case InventoryType::Npc:
#ifdef EATHENA_SUPPORT
case InventoryType::Cart:
case InventoryType::Vending:
case InventoryType::Mail:
case InventoryType::Craft:
#endif
case InventoryType::TypeEnd:
default:
break;
}
addProtection();
if (config.getBoolValue("enablePickupFilter"))
{
mNick = item->getName();
mBrowserBox->addRow("##3---");
addPickupFilter(mNick);
}
// TRANSLATORS: popup menu item
// TRANSLATORS: add item name to chat
mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showItemPopup(const int x, const int y,
const int itemId,
const ItemColor color)
{
const Inventory *const inv = PlayerInfo::getInventory();
if (!inv)
return;
Item *const item = inv->findItem(itemId, color);
if (item)
{
showItemPopup(x, y, item);
}
else
{
mItemId = itemId;
mItemIndex = -1;
mItemColor = color;
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = 0;
mX = x;
mY = y;
mBrowserBox->clearRows();
if (!PlayerInfo::isItemProtected(mItemId))
{
// TRANSLATORS: popup menu item
// TRANSLATORS: use item
mBrowserBox->addRow("/use 'ITEMID'", _("Use"));
}
addProtection();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
}
void PopupMenu::showItemPopup(const int x, const int y,
const Item *const item)
{
mX = x;
mY = y;
if (item)
{
mItemId = item->getId();
mItemColor = item->getColor();
mItemIndex = item->getInvIndex();
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = item->getCard(f);
}
else
{
mItemId = 0;
mItemColor = ItemColor_one;
mItemIndex = -1;
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = 0;
}
mNick.clear();
mBrowserBox->clearRows();
if (item)
{
const bool isProtected = PlayerInfo::isItemProtected(mItemId);
addUseDrop(item, isProtected);
if (InventoryWindow::isStorageActive())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: add item to storage
mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
}
// TRANSLATORS: popup menu item
// TRANSLATORS: add item name to chat
mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
if (config.getBoolValue("enablePickupFilter"))
{
mNick = item->getName();
mBrowserBox->addRow("##3---");
addPickupFilter(mNick);
}
}
addProtection();
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showDropPopup(const int x,
const int y,
const Item *const item)
{
mX = x;
mY = y;
mNick.clear();
mBrowserBox->clearRows();
if (item)
{
mItemId = item->getId();
mItemColor = item->getColor();
mItemIndex = item->getInvIndex();
for (int f = 0; f < maxCards; f ++)
mItemCards[f] = item->getCard(f);
const bool isProtected = PlayerInfo::isItemProtected(mItemId);
addUseDrop(item, isProtected);
if (InventoryWindow::isStorageActive())
{
// TRANSLATORS: popup menu item
// TRANSLATORS: add item to storage
mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
}
addProtection();
// TRANSLATORS: popup menu item
// TRANSLATORS: add item name to chat
mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
if (config.getBoolValue("enablePickupFilter"))
{
mNick = item->getName();
mBrowserBox->addRow("##3---");
addPickupFilter(mNick);
}
}
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
mBrowserBox->addRow("/cleardrops", _("Clear drop window"));
mBrowserBox->addRow("##3---");
// TRANSLATORS: popup menu item
// TRANSLATORS: close menu
mBrowserBox->addRow("cancel", _("Cancel"));
showPopup(x, y);
}
void PopupMenu::showPopup(const int x, const int y, Button *const button)
{
if (!button || !windowMenu)
return;
mButton = button;
mX = x;
mY = y;
mBrowserBox->clearRows();
std::vector