GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/popups/popupmenu.cpp Lines: 21 1624 1.3 %
Date: 2018-09-20 Branches: 16 2129 0.8 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2018  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "gui/popups/popupmenu.h"
24
25
#include "actormanager.h"
26
#include "configuration.h"
27
#include "party.h"
28
#include "settings.h"
29
30
#include "being/flooritem.h"
31
#include "being/localplayer.h"
32
#include "being/playerinfo.h"
33
#include "being/playerrelation.h"
34
#include "being/playerrelations.h"
35
36
#include "const/spells.h"
37
38
#include "enums/resources/map/mapitemtype.h"
39
40
#include "input/inputmanager.h"
41
42
#include "gui/buttontext.h"
43
#include "gui/gui.h"
44
#include "gui/popupmanager.h"
45
#include "gui/viewport.h"
46
#include "gui/windowmenu.h"
47
48
#include "gui/windows/chatwindow.h"
49
#include "gui/windows/inventorywindow.h"
50
#include "gui/windows/minimap.h"
51
#include "gui/windows/ministatuswindow.h"
52
#include "gui/windows/npcdialog.h"
53
#include "gui/windows/outfitwindow.h"
54
#include "gui/windows/socialwindow.h"
55
#include "gui/windows/textcommandeditor.h"
56
#include "gui/windows/textdialog.h"
57
#include "gui/windows/tradewindow.h"
58
59
#include "gui/widgets/button.h"
60
#include "gui/widgets/createwidget.h"
61
#include "gui/widgets/progressbar.h"
62
#include "gui/widgets/scrollarea.h"
63
#include "gui/widgets/staticbrowserbox.h"
64
#include "gui/widgets/textfield.h"
65
66
#include "gui/widgets/tabs/chat/whispertab.h"
67
68
#include "net/adminhandler.h"
69
#include "net/chathandler.h"
70
#include "net/guildhandler.h"
71
#include "net/npchandler.h"
72
#include "net/net.h"
73
74
#ifdef TMWA_SUPPORT
75
#include "net/tmwa/guildmanager.h"
76
#endif  // TMWA_SUPPORT
77
78
#include "resources/chatobject.h"
79
#include "resources/groupinfo.h"
80
#include "resources/iteminfo.h"
81
#include "resources/itemmenuitem.h"
82
83
#include "resources/db/groupdb.h"
84
#include "resources/db/npcdb.h"
85
86
#include "resources/item/item.h"
87
88
#include "resources/map/map.h"
89
#include "resources/map/mapitem.h"
90
#include "resources/map/speciallayer.h"
91
92
#include "resources/skill/skillinfo.h"
93
94
#include "utils/checkutils.h"
95
#include "utils/foreach.h"
96
#include "utils/gettext.h"
97
98
#include "debug.h"
99
100
1
std::string tradePartnerName;
101
102
PopupMenu *popupMenu = nullptr;
103
104
2
PopupMenu::PopupMenu() :
105
    Popup("PopupMenu", "popupmenu.xml"),
106
    mBrowserBox(new StaticBrowserBox(this, Opaque_true,
107

2
        "popupbrowserbox.xml")),
108
    mScrollArea(nullptr),
109
    mBeingId(BeingId_zero),
110
    mFloorItemId(BeingId_zero),
111
    mItemId(0),
112
    mItemIndex(-1),
113
    mItemColor(ItemColor_one),
114
    mMapItem(nullptr),
115
    mTab(nullptr),
116
    mSpell(nullptr),
117
    mCallerWindow(nullptr),
118
    mRenameListener(),
119
    mPlayerListener(),
120
    mDialog(nullptr),
121
    mButton(nullptr),
122
    mGroup(nullptr),
123
    mName(),
124
    mExtName(),
125
    mTextField(nullptr),
126
    mType(ActorType::Unknown),
127
    mSubType(BeingTypeId_zero),
128
    mX(0),
129
    mY(0),
130


28
    mAllowCleanMenu(true)
131
{
132
4
    mBrowserBox->setOpaque(Opaque_false);
133
2
    mBrowserBox->setLinkHandler(this);
134
2
    mRenameListener.setMapItem(nullptr);
135
4
    mRenameListener.setDialog(nullptr);
136
10
    mPlayerListener.setNick("");
137
4
    mPlayerListener.setDialog(nullptr);
138
4
    mPlayerListener.setType(ActorType::Unknown);
139
2
    mScrollArea = new ScrollArea(this,
140

4
        mBrowserBox, Opaque_false, std::string());
141
2
    mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
142
2
    addMouseListener(this);
143
2
}
144
145
2
void PopupMenu::postInit()
146
{
147
4
    Popup::postInit();
148
2
    add(mScrollArea);
149
2
}
150
151
void PopupMenu::initPopup()
152
{
153
    if (localPlayer == nullptr)
154
        return;
155
    const int groupId = localPlayer->getGroupId();
156
    mGroup = GroupDb::getGroup(groupId);
157
}
158
159
bool PopupMenu::isAllowCommand(const ServerCommandTypeT command)
160
{
161
    if (mGroup == nullptr)
162
        return false;
163
#ifdef TMWA_SUPPORT
164
    // allow any commands for legacy if group > 0
165
    if (Net::getNetworkType() == ServerType::TMWATHENA &&
166
        localPlayer != nullptr &&
167
        localPlayer->isGM())
168
    {
169
        return true;
170
    }
171
#endif
172
    if (mGroup->mPermissions[CAST_SIZE(ServerPermissionType::all_commands)] ==
173
        Enable_true)
174
    {
175
        return true;
176
    }
177
    const ServerCommandEnable::Type enabled =
178
        mGroup->mCommands[CAST_SIZE(command)];
179
    return (enabled & ServerCommandEnable::Self) != 0;
180
}
181
182
bool PopupMenu::isAllowOtherCommand(const ServerCommandTypeT command)
183
{
184
    if (mGroup == nullptr ||
185
        localPlayer == nullptr)
186
        return false;
187
#ifdef TMWA_SUPPORT
188
    // allow any commands for legacy if group > 0
189
    if (Net::getNetworkType() == ServerType::TMWATHENA &&
190
        localPlayer->isGM())
191
    {
192
        return true;
193
    }
194
#endif
195
    const ServerCommandEnable::Type enabled =
196
        mGroup->mCommands[CAST_SIZE(command)];
197
    if (mName == localPlayer->getName())
198
        return (enabled & ServerCommandEnable::Self) != 0;
199
    return (enabled & ServerCommandEnable::Other) != 0;
200
}
201
202
void PopupMenu::showPopup(const int x, const int y, const Being *const being)
203
{
204
    if (being == nullptr ||
205
        localPlayer == nullptr ||
206
        actorManager == nullptr)
207
    {
208
        return;
209
    }
210
211
    initPopup();
212
    mBeingId = being->getId();
213
    mName = being->getName();
214
    mExtName = being->getExtName();
215
    mType = being->getType();
216
    mSubType = being->getSubType();
217
    mBrowserBox->clearRows();
218
    mX = x;
219
    mY = y;
220
221
    const std::string &name = mName;
222
    if (being->getType() != ActorType::SkillUnit)
223
    {
224
        mBrowserBox->addRow(name + being->getGenderSignWithSpace(),
225
            false);
226
    }
227
228
    switch (being->getType())
229
    {
230
        case ActorType::Player:
231
        {
232
            // TRANSLATORS: popup menu item
233
            // TRANSLATORS: trade with player
234
            mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
235
            // TRANSLATORS: popup menu item
236
            // TRANSLATORS: trade attack player
237
            mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
238
            // TRANSLATORS: popup menu item
239
            // TRANSLATORS: send whisper to player
240
            mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
241
            addMailCommands();
242
            addGmCommands();
243
            mBrowserBox->addSeparator("##3---");
244
245
#ifdef TMWA_SUPPORT
246
            if (Net::getNetworkType() == ServerType::TMWATHENA)
247
            {
248
                // TRANSLATORS: popup menu item
249
                // TRANSLATORS: heal player
250
                mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
251
                mBrowserBox->addSeparator("##3---");
252
            }
253
#endif  // TMWA_SUPPORT
254
255
            addPlayerRelation(name);
256
            mBrowserBox->addSeparator("##3---");
257
258
            addFollow();
259
            addPartyName(being->getPartyName());
260
261
            const Guild *const guild1 = being->getGuild();
262
            const Guild *const guild2 = localPlayer->getGuild();
263
            if (guild2 != nullptr)
264
            {
265
                if (guild1 != nullptr)
266
                {
267
                    if (guild1->getId() == guild2->getId())
268
                    {
269
                        mBrowserBox->addRow("/kickguild 'NAME'",
270
                            // TRANSLATORS: popup menu item
271
                            // TRANSLATORS: kick player from guild
272
                            _("Kick from guild"));
273
                        if (guild2->getServerGuild())
274
                        {
275
                            mBrowserBox->addRow(strprintf(
276
                                "@@guild-pos|%s >@@",
277
                                // TRANSLATORS: popup menu item
278
                                // TRANSLATORS: change player position in guild
279
                                _("Change pos in guild")),
280
                                false);
281
                        }
282
                    }
283
                }
284
                else if (guild2->getMember(mName) != nullptr)
285
                {
286
                    mBrowserBox->addRow("/kickguild 'NAME'",
287
                        // TRANSLATORS: popup menu item
288
                        // TRANSLATORS: kick player from guild
289
                        _("Kick from guild"));
290
                    if (guild2->getServerGuild())
291
                    {
292
                        mBrowserBox->addRow(strprintf(
293
                            "@@guild-pos|%s >@@",
294
                            // TRANSLATORS: popup menu item
295
                            // TRANSLATORS: change player position in guild
296
                            _("Change pos in guild")),
297
                            false);
298
                    }
299
                }
300
                else
301
                {
302
#ifdef TMWA_SUPPORT
303
                    if (guild2->getServerGuild() ||
304
                        (guildManager != nullptr && guildManager->havePower()))
305
#endif  // TMWA_SUPPORT
306
                    {
307
                        mBrowserBox->addRow("/guild 'NAME'",
308
                            // TRANSLATORS: popup menu item
309
                            // TRANSLATORS: invite player to guild
310
                            _("Invite to guild"));
311
                    }
312
                }
313
            }
314
315
            // TRANSLATORS: popup menu item
316
            // TRANSLATORS: set player invisible for self by id
317
            mBrowserBox->addRow("/nuke 'NAME'", _("Nuke"));
318
            // TRANSLATORS: popup menu item
319
            // TRANSLATORS: move to player location
320
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
321
            addPlayerMisc();
322
            addBuySell(being);
323
            addChat(being);
324
            break;
325
        }
326
327
        case ActorType::Npc:
328
            if (!addBeingMenu())
329
            {
330
                // TRANSLATORS: popup menu item
331
                // TRANSLATORS: talk with npc
332
                mBrowserBox->addRow("/talk :'BEINGID'", _("Talk"));
333
#ifdef TMWA_SUPPORT
334
                if (Net::getNetworkType() != ServerType::TMWATHENA)
335
#endif
336
                {
337
                    mBrowserBox->addRow("/whispertext NPC:'NAME'",
338
                        // TRANSLATORS: popup menu item
339
                        // TRANSLATORS: whisper to npc
340
                        _("Whisper"));
341
                }
342
                // TRANSLATORS: popup menu item
343
                // TRANSLATORS: buy from npc
344
                mBrowserBox->addRow("/buy 'NAME'", _("Buy"));
345
                // TRANSLATORS: popup menu item
346
                // TRANSLATORS: sell to npc
347
                mBrowserBox->addRow("/sell 'NAME'", _("Sell"));
348
            }
349
350
            addGmCommands();
351
            mBrowserBox->addSeparator("##3---");
352
            // TRANSLATORS: popup menu item
353
            // TRANSLATORS: move to npc location
354
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
355
            // TRANSLATORS: popup menu item
356
            // TRANSLATORS: add comment to npc
357
            mBrowserBox->addRow("addcomment", _("Add comment"));
358
            addChat(being);
359
            break;
360
361
        case ActorType::Monster:
362
        {
363
            // Monsters can be attacked
364
            // TRANSLATORS: popup menu item
365
            // TRANSLATORS: attack monster
366
            mBrowserBox->addRow("/attack :'BEINGID'", _("Attack"));
367
            addCatchPetCommands();
368
            addGmCommands();
369
            mBrowserBox->addSeparator("##3---");
370
371
            if (config.getBoolValue("enableAttackFilter"))
372
            {
373
                mBrowserBox->addSeparator("##3---");
374
                if (actorManager->isInAttackList(name)
375
                    || actorManager->isInIgnoreAttackList(name)
376
                    || actorManager->isInPriorityAttackList(name))
377
                {
378
                    mBrowserBox->addRow("/removeattack 'NAME'",
379
                        // TRANSLATORS: remove monster from attack list
380
                        // TRANSLATORS: popup menu item
381
                        _("Remove from attack list"));
382
                }
383
                else
384
                {
385
                    mBrowserBox->addRow("/addpriorityattack 'NAME'",
386
                        // TRANSLATORS: popup menu item
387
                        // TRANSLATORS: add monster to priotiry attack list
388
                        _("Add to priority attack list"));
389
                    mBrowserBox->addRow("/addattack 'NAME'",
390
                        // TRANSLATORS: popup menu item
391
                        // TRANSLATORS: add monster to attack list
392
                        _("Add to attack list"));
393
                    mBrowserBox->addRow("/addignoreattack 'NAME'",
394
                        // TRANSLATORS: popup menu item
395
                        // TRANSLATORS: add monster to ignore list
396
                        _("Add to ignore list"));
397
                }
398
            }
399
            break;
400
        }
401
402
        case ActorType::Mercenary:
403
            // TRANSLATORS: popup menu item
404
            // TRANSLATORS: Mercenary move to master
405
            mBrowserBox->addRow("/mercenarytomaster", _("Move to master"));
406
            addGmCommands();
407
            mBrowserBox->addSeparator("##3---");
408
            // TRANSLATORS: popup menu item
409
            // TRANSLATORS: fire mercenary
410
            mBrowserBox->addRow("/firemercenary", _("Fire"));
411
            mBrowserBox->addSeparator("##3---");
412
            break;
413
414
        case ActorType::Homunculus:
415
        {
416
            const HomunculusInfo *const info = PlayerInfo::getHomunculus();
417
            if (info != nullptr)
418
            {
419
                mBrowserBox->addRow("/homunculustomaster",
420
                    // TRANSLATORS: popup menu item
421
                    // TRANSLATORS: homunculus move to master
422
                    _("Move to master"));
423
                // TRANSLATORS: popup menu item
424
                // TRANSLATORS: feed homunculus
425
                mBrowserBox->addRow("/homunculusfeed", _("Feed"));
426
                mBrowserBox->addSeparator("##3---");
427
                // TRANSLATORS: popup menu item
428
                // TRANSLATORS: pet rename item
429
                mBrowserBox->addRow("/sethomunname", _("Rename"));
430
                mBrowserBox->addSeparator("##3---");
431
                // TRANSLATORS: popup menu item
432
                // TRANSLATORS: delete homunculus
433
                mBrowserBox->addRow("/homunculusfire", _("Kill"));
434
                mBrowserBox->addSeparator("##3---");
435
            }
436
            addGmCommands();
437
            break;
438
        }
439
        case ActorType::Pet:
440
            if (being->getOwner() == localPlayer)
441
            {
442
                // TRANSLATORS: popup menu item
443
                // TRANSLATORS: feed pet
444
                mBrowserBox->addRow("/petfeed", _("Feed"));
445
                // TRANSLATORS: popup menu item
446
                // TRANSLATORS: pet drop loot
447
                mBrowserBox->addRow("/petdroploot", _("Drop loot"));
448
                // TRANSLATORS: popup menu item
449
                // TRANSLATORS: pet unequip item
450
                mBrowserBox->addRow("/petunequip", _("Unequip"));
451
                addGmCommands();
452
                mBrowserBox->addSeparator("##3---");
453
                // TRANSLATORS: popup menu item
454
                // TRANSLATORS: pet rename item
455
                mBrowserBox->addRow("/setpetname", _("Rename"));
456
                mBrowserBox->addSeparator("##3---");
457
                const BeingInfo *const info = being->getInfo();
458
                std::string msg;
459
                if (info != nullptr)
460
                    msg = info->getString(0);
461
                if (!msg.empty())
462
                {
463
                    mBrowserBox->addRow("/petreturnegg", msg.c_str());
464
                }
465
                else
466
                {
467
                    mBrowserBox->addRow("/petreturnegg",
468
                        // TRANSLATORS: popup menu item
469
                        // TRANSLATORS: pet return to egg
470
                        _("Return to egg"));
471
                }
472
                mBrowserBox->addSeparator("##3---");
473
            }
474
            else
475
            {
476
                addCatchPetCommands();
477
            }
478
            break;
479
        case ActorType::SkillUnit:
480
        {
481
            const BeingId id = being->getCreatorId();
482
            std::string creatorName;
483
            Being *const creator = actorManager->findBeing(id);
484
            if (creator != nullptr)
485
                creatorName = creator->getName();
486
            else
487
                creatorName = actorManager->getSeenPlayerById(id);
488
489
            if (creatorName.empty())
490
                creatorName = strprintf("?%d", CAST_S32(id));
491
492
            mBrowserBox->addRow(strprintf("%s, %d (%s)",
493
                name.c_str(),
494
                CAST_S32(being->getSubType()),
495
                creatorName.c_str()),
496
                false);
497
            break;
498
        }
499
        case ActorType::Avatar:
500
        case ActorType::Unknown:
501
        case ActorType::FloorItem:
502
        case ActorType::Portal:
503
        case ActorType::Elemental:
504
        default:
505
            break;
506
    }
507
    // TRANSLATORS: popup menu item
508
    // TRANSLATORS: add being name to chat
509
    mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
510
    mBrowserBox->addSeparator("##3---");
511
512
    // TRANSLATORS: popup menu item
513
    // TRANSLATORS: close menu
514
    mBrowserBox->addRow("cancel", _("Cancel"));
515
516
    showPopup(x, y);
517
}
518
519
bool PopupMenu::addBeingMenu()
520
{
521
    Being *being = actorManager->findBeing(mBeingId);
522
    if (being == nullptr)
523
        return false;
524
525
    BeingInfo *const info = NPCDB::get(fromInt(
526
        being->getSubType(), BeingTypeId));
527
    if (info == nullptr)
528
        return false;
529
530
    const STD_VECTOR<BeingMenuItem> &menu = info->getMenu();
531
    FOR_EACH (STD_VECTOR<BeingMenuItem>::const_iterator, it, menu)
532
    {
533
        const BeingMenuItem &item = *it;
534
        mBrowserBox->addRow("/" + item.command, item.name.c_str());
535
    }
536
    return true;
537
}
538
539
void PopupMenu::setMousePos()
540
{
541
    if (viewport != nullptr)
542
    {
543
        mX = viewport->mMouseX;
544
        mY = viewport->mMouseY;
545
    }
546
    else
547
    {
548
        Gui::getMouseState(mX, mY);
549
    }
550
}
551
552
void PopupMenu::setMousePos2()
553
{
554
    if (mX == 0 && mY == 0)
555
    {
556
        if (viewport != nullptr)
557
        {
558
            mX = viewport->mMouseX;
559
            mY = viewport->mMouseY;
560
        }
561
        else
562
        {
563
            Gui::getMouseState(mX, mY);
564
        }
565
    }
566
}
567
568
void PopupMenu::showPopup(const int x, const int y,
569
                          const STD_VECTOR<ActorSprite*> &beings)
570
{
571
    initPopup();
572
    mX = x;
573
    mY = y;
574
    mBrowserBox->clearRows();
575
    // TRANSLATORS: popup menu header
576
    mBrowserBox->addRow(_("Players"), false);
577
    FOR_EACH (STD_VECTOR<ActorSprite*>::const_iterator, it, beings)
578
    {
579
        const Being *const being = dynamic_cast<const Being*>(*it);
580
        const ActorSprite *const actor = *it;
581
        if ((being != nullptr) && !being->getName().empty())
582
        {
583
            mBrowserBox->addRow(strprintf("@@player_%u|%s >@@",
584
                CAST_U32(being->getId()), (being->getName()
585
                + being->getGenderSignWithSpace()).c_str()),
586
                false);
587
        }
588
        else if (actor->getType() == ActorType::FloorItem)
589
        {
590
            const FloorItem *const floorItem
591
                = static_cast<const FloorItem*>(actor);
592
            mBrowserBox->addRow(strprintf("@@flooritem_%u|%s >@@",
593
                CAST_U32(actor->getId()),
594
                floorItem->getName().c_str()),
595
                false);
596
        }
597
    }
598
    mBrowserBox->addSeparator("##3---");
599
    // TRANSLATORS: popup menu item
600
    // TRANSLATORS: close menu
601
    mBrowserBox->addRow("cancel", _("Cancel"));
602
    showPopup(x, y);
603
}
604
605
void PopupMenu::showPlayerPopup(const std::string &nick)
606
{
607
    if (nick.empty() || (localPlayer == nullptr))
608
        return;
609
610
    initPopup();
611
    setMousePos();
612
    mName = nick;
613
    mExtName = nick;
614
    mBeingId = BeingId_zero;
615
    mType = ActorType::Player;
616
    mSubType = BeingTypeId_zero;
617
    mBrowserBox->clearRows();
618
619
    const std::string &name = mName;
620
621
    mBrowserBox->addRow(name, false);
622
623
    // TRANSLATORS: popup menu item
624
    // TRANSLATORS: send whisper to player
625
    mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
626
    addMailCommands();
627
    addGmCommands();
628
    mBrowserBox->addSeparator("##3---");
629
630
    addPlayerRelation(name);
631
    mBrowserBox->addSeparator("##3---");
632
633
    addFollow();
634
    // TRANSLATORS: popup menu item
635
    // TRANSLATORS: add comment to player
636
    mBrowserBox->addRow("addcomment", _("Add comment"));
637
638
    if (localPlayer->isInParty())
639
    {
640
        const Party *const party = localPlayer->getParty();
641
        if (party != nullptr)
642
        {
643
            const PartyMember *const member = party->getMember(mName);
644
            if (member != nullptr)
645
            {
646
                // TRANSLATORS: popup menu item
647
                // TRANSLATORS: kick player from party
648
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
649
                mBrowserBox->addSeparator("##3---");
650
                const PartyMember *const o = party->getMember(
651
                    localPlayer->getName());
652
                showAdoptCommands();
653
                if ((o != nullptr) && member->getMap() == o->getMap())
654
                {
655
                    // TRANSLATORS: popup menu item
656
                    // TRANSLATORS: move to player position
657
                    mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
658
                }
659
            }
660
        }
661
    }
662
663
    const Guild *const guild2 = localPlayer->getGuild();
664
    if (guild2 != nullptr)
665
    {
666
        if (guild2->getMember(mName) != nullptr)
667
        {
668
#ifdef TMWA_SUPPORT
669
            if (guild2->getServerGuild() || (guildManager != nullptr
670
                && guildManager->havePower()))
671
#endif  // TMWA_SUPPORT
672
            {
673
                mBrowserBox->addRow("/kickguild 'NAME'",
674
                    // TRANSLATORS: popup menu item
675
                    // TRANSLATORS: kick player from guild
676
                    _("Kick from guild"));
677
            }
678
            if (guild2->getServerGuild())
679
            {
680
                mBrowserBox->addRow(strprintf(
681
                    // TRANSLATORS: popup menu item
682
                    // TRANSLATORS: change player position in guild
683
                    "@@guild-pos|%s >@@", _("Change pos in guild")),
684
                    false);
685
            }
686
        }
687
        else
688
        {
689
#ifdef TMWA_SUPPORT
690
            if (guild2->getServerGuild() || (guildManager != nullptr
691
                && guildManager->havePower()))
692
#endif  // TMWA_SUPPORT
693
            {
694
                // TRANSLATORS: popup menu item
695
                // TRANSLATORS: invite player to guild
696
                mBrowserBox->addRow("/guild 'NAME'", _("Invite to guild"));
697
            }
698
        }
699
    }
700
701
    addBuySellDefault();
702
    // TRANSLATORS: popup menu item
703
    // TRANSLATORS: add player name to chat
704
    mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
705
    mBrowserBox->addSeparator("##3---");
706
    // TRANSLATORS: popup menu item
707
    // TRANSLATORS: close menu
708
    mBrowserBox->addRow("cancel", _("Cancel"));
709
710
    showPopup(mX, mY);
711
}
712
713
void PopupMenu::showPopup(const int x, const int y,
714
                          const FloorItem *const floorItem)
715
{
716
    if (floorItem == nullptr)
717
        return;
718
719
    initPopup();
720
    mX = x;
721
    mY = y;
722
    mFloorItemId = floorItem->getId();
723
    mItemId = floorItem->getItemId();
724
    mType = ActorType::FloorItem;
725
    mSubType = BeingTypeId_zero;
726
    for (int f = 0; f < maxCards; f ++)
727
        mItemCards[f] = floorItem->getCard(f);
728
    mBrowserBox->clearRows();
729
    const std::string name = floorItem->getName();
730
    mName = name;
731
    mExtName = name;
732
733
    mBrowserBox->addRow(name, false);
734
735
    if (config.getBoolValue("enablePickupFilter"))
736
    {
737
        if (actorManager->isInPickupList(name)
738
            || (actorManager->isInPickupList("")
739
            && !actorManager->isInIgnorePickupList(name)))
740
        {
741
            // TRANSLATORS: popup menu item
742
            // TRANSLATORS: pickup item from ground
743
            mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
744
            mBrowserBox->addSeparator("##3---");
745
        }
746
        addPickupFilter(name);
747
    }
748
    else
749
    {
750
        // TRANSLATORS: popup menu item
751
        // TRANSLATORS: pickup item from ground
752
        mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
753
    }
754
    addProtection();
755
    // TRANSLATORS: popup menu item
756
    // TRANSLATORS: add item name to chat
757
    mBrowserBox->addRow("/addchat 'FLOORID''CARDS'", _("Add to chat"));
758
    mBrowserBox->addSeparator("##3---");
759
    addGmCommands();
760
761
    // TRANSLATORS: popup menu item
762
    // TRANSLATORS: close menu
763
    mBrowserBox->addRow("cancel", _("Cancel"));
764
765
    showPopup(mX, mY);
766
}
767
768
void PopupMenu::showPopup(const int x, const int y, MapItem *const mapItem)
769
{
770
    if (mapItem == nullptr)
771
        return;
772
773
    initPopup();
774
    mMapItem = mapItem;
775
    mX = x;
776
    mY = y;
777
778
    mBrowserBox->clearRows();
779
780
    // TRANSLATORS: popup menu header
781
    mBrowserBox->addRow(_("Map Item"), false);
782
    // TRANSLATORS: popup menu item
783
    // TRANSLATORS: rename map item
784
    mBrowserBox->addRow("rename map", _("Rename"));
785
    // TRANSLATORS: popup menu item
786
    // TRANSLATORS: remove map item
787
    mBrowserBox->addRow("remove map", _("Remove"));
788
789
    if (isAllowCommand(ServerCommandType::slide))
790
    {
791
        mBrowserBox->addSeparator("##3---");
792
        // TRANSLATORS: popup menu item
793
        // TRANSLATORS: warp to map item
794
        mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
795
    }
796
    mBrowserBox->addSeparator("##3---");
797
    // TRANSLATORS: popup menu item
798
    // TRANSLATORS: close menu
799
    mBrowserBox->addRow("cancel", _("Cancel"));
800
801
    showPopup(x, y);
802
}
803
804
void PopupMenu::showMapPopup(const int x, const int y,
805
                             const int x2, const int y2,
806
                             const bool isMinimap)
807
{
808
    initPopup();
809
    mX = x2;
810
    mY = y2;
811
812
    if (isMinimap)
813
        mCallerWindow = minimap;
814
815
    mBrowserBox->clearRows();
816
817
    // TRANSLATORS: popup menu header
818
    mBrowserBox->addRow(_("Map Item"), false);
819
820
    if (isAllowCommand(ServerCommandType::slide))
821
    {
822
        // TRANSLATORS: popup menu item
823
        // TRANSLATORS: warp to map item
824
        mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
825
    }
826
    // TRANSLATORS: popup menu item
827
    // TRANSLATORS: move to map item
828
    mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
829
    // TRANSLATORS: popup menu item
830
    // TRANSLATORS: move camera to map item
831
    mBrowserBox->addRow("/movecamera 'X' 'Y'", _("Move camera"));
832
    if (settings.cameraMode != 0)
833
    {
834
        // TRANSLATORS: popup menu item
835
        // TRANSLATORS: restore camera to default view
836
        mBrowserBox->addRow("/restorecamera", _("Restore camera"));
837
    }
838
    mBrowserBox->addSeparator("##3---");
839
    if (isMinimap)
840
    {
841
        // TRANSLATORS: popup menu item
842
        mBrowserBox->addRow("window close", _("Close"));
843
    }
844
    mBrowserBox->addSeparator("##3---");
845
    // TRANSLATORS: popup menu item
846
    // TRANSLATORS: close menu
847
    mBrowserBox->addRow("cancel", _("Cancel"));
848
849
    showPopup(x, y);
850
}
851
852
void PopupMenu::showOutfitsWindowPopup(const int x, const int y)
853
{
854
    initPopup();
855
    mX = x;
856
    mY = y;
857
    mCallerWindow = outfitWindow;
858
859
    mBrowserBox->clearRows();
860
861
    // TRANSLATORS: popup menu header
862
    mBrowserBox->addRow(_("Outfits"), false);
863
    // TRANSLATORS: popup menu item
864
    // TRANSLATORS: copy selected outfit to chat input
865
    mBrowserBox->addRow("/outfittochat", _("Add to chat"));
866
    mBrowserBox->addSeparator("##3---");
867
    // TRANSLATORS: popup menu item
868
    // TRANSLATORS: copy equipment from player to outfit
869
    mBrowserBox->addRow("/itemstooutfit", _("Copy from player"));
870
    mBrowserBox->addSeparator("##3---");
871
    // TRANSLATORS: popup menu item
872
    // TRANSLATORS: clear selected outfit
873
    mBrowserBox->addRow("/clearoutfit", _("Clear outfit"));
874
    mBrowserBox->addSeparator("##3---");
875
876
    addWindowMenu(outfitWindow);
877
    mBrowserBox->addSeparator("##3---");
878
879
    // TRANSLATORS: popup menu item
880
    // TRANSLATORS: close menu
881
    mBrowserBox->addRow("cancel", _("Cancel"));
882
883
    showPopup(x, y);
884
}
885
886
void PopupMenu::showSpellPopup(const int x, const int y,
887
                               TextCommand *const cmd)
888
{
889
    if (cmd == nullptr)
890
        return;
891
892
    initPopup();
893
    mBrowserBox->clearRows();
894
895
    mSpell = cmd;
896
    mX = x;
897
    mY = y;
898
899
    // TRANSLATORS: popup menu header
900
    mBrowserBox->addRow(_("Spells"), false);
901
    // TRANSLATORS: popup menu item
902
    // TRANSLATORS: edit selected spell
903
    mBrowserBox->addRow("edit spell", _("Edit spell"));
904
    mBrowserBox->addSeparator("##3---");
905
    // TRANSLATORS: popup menu item
906
    // TRANSLATORS: close menu
907
    mBrowserBox->addRow("cancel", _("Cancel"));
908
909
    showPopup(x, y);
910
}
911
912
void PopupMenu::showChatPopup(const int x, const int y, ChatTab *const tab)
913
{
914
    if (tab == nullptr ||
915
        actorManager == nullptr ||
916
        localPlayer == nullptr)
917
    {
918
        return;
919
    }
920
921
    initPopup();
922
    mTab = tab;
923
    mX = x;
924
    mY = y;
925
    mCallerWindow = chatWindow;
926
927
    mBrowserBox->clearRows();
928
929
    const ChatTabTypeT &type = tab->getType();
930
    if (type == ChatTabType::WHISPER || type == ChatTabType::CHANNEL)
931
    {
932
        // TRANSLATORS: popup menu item
933
        // TRANSLATORS: close chat tab
934
        mBrowserBox->addRow("/close", _("Close"));
935
    }
936
937
    // TRANSLATORS: popup menu item
938
    // TRANSLATORS: remove all text from chat tab
939
    mBrowserBox->addRow("/chatclear", _("Clear"));
940
    mBrowserBox->addSeparator("##3---");
941
942
    if (tab->getAllowHighlight())
943
    {
944
        // TRANSLATORS: popup menu item
945
        // TRANSLATORS: disable chat tab highlight
946
        mBrowserBox->addRow("/disablehighlight", _("Disable highlight"));
947
    }
948
    else
949
    {
950
        // TRANSLATORS: popup menu item
951
        // TRANSLATORS: enable chat tab highlight
952
        mBrowserBox->addRow("/enablehighlight", _("Enable highlight"));
953
    }
954
    if (tab->getRemoveNames())
955
    {
956
        // TRANSLATORS: popup menu item
957
        // TRANSLATORS: do not remove player names from chat tab
958
        mBrowserBox->addRow("/dontremovename", _("Don't remove name"));
959
    }
960
    else
961
    {
962
        // TRANSLATORS: popup menu item
963
        // TRANSLATORS: remove player names from chat tab
964
        mBrowserBox->addRow("/removename", _("Remove name"));
965
    }
966
    if (tab->getNoAway())
967
    {
968
        // TRANSLATORS: popup menu item
969
        // TRANSLATORS: enable away messages in chat tab
970
        mBrowserBox->addRow("/enableaway", _("Enable away"));
971
    }
972
    else
973
    {
974
        // TRANSLATORS: popup menu item
975
        // TRANSLATORS: disable away messages in chat tab
976
        mBrowserBox->addRow("/disableaway", _("Disable away"));
977
    }
978
    mBrowserBox->addSeparator("##3---");
979
    if (type == ChatTabType::PARTY)
980
    {
981
        // TRANSLATORS: popup menu item
982
        // TRANSLATORS: enable away messages in chat tab
983
        mBrowserBox->addRow("/leaveparty", _("Leave"));
984
        mBrowserBox->addSeparator("##3---");
985
    }
986
    // TRANSLATORS: popup menu item
987
    // TRANSLATORS: copy selected text to clipboard
988
    mBrowserBox->addRow("/chatclipboard 'X' 'Y'", _("Copy to clipboard"));
989
    mBrowserBox->addSeparator("##3---");
990
991
    if (type == ChatTabType::WHISPER)
992
    {
993
        const WhisperTab *const wTab = static_cast<WhisperTab*>(tab);
994
        const std::string &name = wTab->getNick();
995
996
        const Being* const being  = actorManager->findBeingByName(
997
            name, ActorType::Player);
998
999
        addGmCommands();
1000
        if (being != nullptr)
1001
        {
1002
            mBeingId = being->getId();
1003
            mName = being->getName();
1004
            mExtName = being->getExtName();
1005
            mType = being->getType();
1006
            mSubType = being->getSubType();
1007
1008
            // TRANSLATORS: popup menu item
1009
            // TRANSLATORS: trade with player
1010
            mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
1011
            // TRANSLATORS: popup menu item
1012
            // TRANSLATORS: attack player
1013
            mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
1014
            addMailCommands();
1015
            mBrowserBox->addSeparator("##3---");
1016
            // TRANSLATORS: popup menu item
1017
            // TRANSLATORS: heal player
1018
            mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
1019
            mBrowserBox->addSeparator("##3---");
1020
            addPlayerRelation(name);
1021
            mBrowserBox->addSeparator("##3---");
1022
            addFollow();
1023
            // TRANSLATORS: popup menu item
1024
            // TRANSLATORS: move to player position
1025
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
1026
            addPlayerMisc();
1027
            addBuySell(being);
1028
            mBrowserBox->addSeparator("##3---");
1029
            addParty(wTab->getNick());
1030
            const Guild *const guild1 = being->getGuild();
1031
            const Guild *const guild2 = localPlayer->getGuild();
1032
            if (guild2 != nullptr)
1033
            {
1034
                if (guild1 != nullptr)
1035
                {
1036
                    if (guild1->getId() == guild2->getId())
1037
                    {
1038
#ifdef TMWA_SUPPORT
1039
                        if (guild2->getServerGuild() ||
1040
                            (guildManager != nullptr &&
1041
                            guildManager->havePower()))
1042
#endif  // TMWA_SUPPORT
1043
                        {
1044
                            mBrowserBox->addRow("/kickguild 'NAME'",
1045
                                // TRANSLATORS: popup menu item
1046
                                // TRANSLATORS: kick player from guild
1047
                                _("Kick from guild"));
1048
                        }
1049
                        if (guild2->getServerGuild())
1050
                        {
1051
                            mBrowserBox->addRow(strprintf("@@guild-pos|%s >@@",
1052
                                // TRANSLATORS: popup menu item
1053
                                // TRANSLATORS: change player position in guild
1054
                                 _("Change pos in guild")),
1055
                                false);
1056
                        }
1057
                    }
1058
                }
1059
                else
1060
                {
1061
#ifdef TMWA_SUPPORT
1062
                    if (guild2->getServerGuild() || (guildManager != nullptr
1063
                        && guildManager->havePower()))
1064
#endif  // TMWA_SUPPORT
1065
                    {
1066
                        mBrowserBox->addRow("/guild 'NAME'",
1067
                            // TRANSLATORS: popup menu item
1068
                            // TRANSLATORS: invite player to guild
1069
                            _("Invite to guild"));
1070
                    }
1071
                }
1072
            }
1073
        }
1074
        else
1075
        {
1076
            mBeingId = BeingId_zero;
1077
            mName = name;
1078
            mExtName = name;
1079
            mType = ActorType::Player;
1080
            mSubType = BeingTypeId_zero;
1081
            addPlayerRelation(name);
1082
            mBrowserBox->addSeparator("##3---");
1083
            addMailCommands();
1084
            addFollow();
1085
1086
            if (localPlayer->isInParty())
1087
            {
1088
                const Party *const party = localPlayer->getParty();
1089
                if (party != nullptr)
1090
                {
1091
                    const PartyMember *const m = party->getMember(mName);
1092
                    if (m != nullptr)
1093
                    {
1094
                        // TRANSLATORS: popup menu item
1095
                        // TRANSLATORS: move to player location
1096
                        mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
1097
                    }
1098
                }
1099
            }
1100
            addPlayerMisc();
1101
            addBuySellDefault();
1102
            if (Net::getNetworkType() != ServerType::TMWATHENA)
1103
                addParty(wTab->getNick());
1104
            mBrowserBox->addSeparator("##3---");
1105
        }
1106
    }
1107
1108
    addWindowMenu(chatWindow);
1109
    // TRANSLATORS: popup menu item
1110
    // TRANSLATORS: close menu
1111
    mBrowserBox->addRow("cancel", _("Cancel"));
1112
1113
    showPopup(x, y);
1114
}
1115
1116
void PopupMenu::showChangePos(const int x, const int y)
1117
{
1118
    initPopup();
1119
    mBrowserBox->clearRows();
1120
    // TRANSLATORS: popup menu header
1121
    mBrowserBox->addRow(_("Change guild position"), false);
1122
1123
    if (localPlayer == nullptr)
1124
        return;
1125
1126
    mX = x;
1127
    mY = y;
1128
    const Guild *const guild = localPlayer->getGuild();
1129
    if (guild != nullptr)
1130
    {
1131
        const PositionsMap &map = guild->getPositions();
1132
        FOR_EACH (PositionsMap::const_iterator, itr, map)
1133
        {
1134
            mBrowserBox->addRow(strprintf("@@guild-pos-%u|%[email protected]@",
1135
                itr->first, itr->second.c_str()),
1136
                false);
1137
        }
1138
        // TRANSLATORS: popup menu item
1139
        // TRANSLATORS: close menu
1140
        mBrowserBox->addRow("cancel", _("Cancel"));
1141
1142
        showPopup(x, y);
1143
    }
1144
    else
1145
    {
1146
        mBeingId = BeingId_zero;
1147
        mFloorItemId = BeingId_zero;
1148
        mItemIndex = -1;
1149
        mItemId = 0;
1150
        for (int f = 0; f < maxCards; f ++)
1151
            mItemCards[f] = 0;
1152
        mMapItem = nullptr;
1153
        mName.clear();
1154
        mExtName.clear();
1155
        mType = ActorType::Unknown;
1156
        mSubType = BeingTypeId_zero;
1157
        mX = 0;
1158
        mY = 0;
1159
        setVisible(Visible_false);
1160
    }
1161
}
1162
1163
void PopupMenu::showWindowPopup(Window *const window)
1164
{
1165
    if (window == nullptr)
1166
        return;
1167
1168
    initPopup();
1169
    setMousePos();
1170
    mCallerWindow = window;
1171
    mBrowserBox->clearRows();
1172
    // TRANSLATORS: popup menu header
1173
    mBrowserBox->addRow(_("window"), false);
1174
1175
    addWindowMenu(window);
1176
1177
    // TRANSLATORS: popup menu item
1178
    // TRANSLATORS: close menu
1179
    mBrowserBox->addRow("cancel", _("Cancel"));
1180
1181
    showPopup(mX, mY);
1182
}
1183
1184
void PopupMenu::addWindowMenu(const Window *const window)
1185
{
1186
    if (window == nullptr)
1187
        return;
1188
1189
    initPopup();
1190
    if (window->getAlowClose())
1191
    {
1192
        // TRANSLATORS: popup menu item
1193
        // TRANSLATORS: close window
1194
        mBrowserBox->addRow("window close", _("Close"));
1195
    }
1196
1197
    if (window->isStickyButtonLock())
1198
    {
1199
        if (window->isSticky())
1200
        {
1201
            // TRANSLATORS: popup menu item
1202
            // TRANSLATORS: unlock window
1203
            mBrowserBox->addRow("window unlock", _("Unlock"));
1204
        }
1205
        else
1206
        {
1207
            // TRANSLATORS: popup menu item
1208
            // TRANSLATORS: lock window
1209
            mBrowserBox->addRow("window lock", _("Lock"));
1210
        }
1211
    }
1212
}
1213
1214
void PopupMenu::showEmoteType()
1215
{
1216
    initPopup();
1217
    setMousePos();
1218
1219
    mBrowserBox->clearRows();
1220
    // TRANSLATORS: popup menu header
1221
    mBrowserBox->addRow(_("Show emotes for:"), false);
1222
1223
    // TRANSLATORS: popup menu item
1224
    // TRANSLATORS: show emotes for player
1225
    mBrowserBox->addRow("/setemotetype player", _("Player"));
1226
1227
    // TRANSLATORS: popup menu item
1228
    // TRANSLATORS: show emotes for pet
1229
    mBrowserBox->addRow("/setemotetype pet", _("Pet"));
1230
1231
    if (Net::getNetworkType() == ServerType::EVOL2)
1232
    {
1233
        // TRANSLATORS: popup menu item
1234
        // TRANSLATORS: show emotes for homuncules
1235
        mBrowserBox->addRow("/setemotetype homun", _("Homunculus"));
1236
1237
        // TRANSLATORS: popup menu item
1238
        // TRANSLATORS: show emotes for mercenary
1239
        mBrowserBox->addRow("/setemotetype merc", _("Mercenary"));
1240
    }
1241
    mBrowserBox->addSeparator("##3---");
1242
1243
    // TRANSLATORS: popup menu item
1244
    // TRANSLATORS: close menu
1245
    mBrowserBox->addRow("cancel", _("Cancel"));
1246
1247
    showPopup(mX, mY);
1248
}
1249
1250
void PopupMenu::handleLink(const std::string &link,
1251
                           MouseEvent *event A_UNUSED)
1252
{
1253
    Being *being = nullptr;
1254
    if (actorManager != nullptr)
1255
        being = actorManager->findBeing(mBeingId);
1256
1257
    mAllowCleanMenu = true;
1258
1259
    if (link == "remove map" && (mMapItem != nullptr))
1260
    {
1261
        if (viewport != nullptr)
1262
        {
1263
            const Map *const map = viewport->getMap();
1264
            if (map != nullptr)
1265
            {
1266
                SpecialLayer *const specialLayer = map->getSpecialLayer();
1267
                if (specialLayer != nullptr)
1268
                {
1269
                    const bool isHome = (mMapItem->getType()
1270
                        == CAST_S32(MapItemType::HOME));
1271
                    const int x = static_cast<int>(mMapItem->getX());
1272
                    const int y = static_cast<int>(mMapItem->getY());
1273
                    specialLayer->setTile(x, y,
1274
                        CAST_S32(MapItemType::EMPTY));
1275
                    specialLayer->updateCache();
1276
                    if (socialWindow != nullptr)
1277
                        socialWindow->removePortal(x, y);
1278
                    if (isHome && (localPlayer != nullptr))
1279
                    {
1280
                        localPlayer->removeHome();
1281
                        localPlayer->saveHomes();
1282
                    }
1283
                }
1284
            }
1285
        }
1286
    }
1287
    else if (link == "rename map" && (mMapItem != nullptr))
1288
    {
1289
        mRenameListener.setMapItem(mMapItem);
1290
        CREATEWIDGETV(mDialog, TextDialog,
1291
            // TRANSLATORS: dialog caption
1292
            // TRANSLATORS: number of chars in string should be near original
1293
            _("Rename map sign          "),
1294
            // TRANSLATORS: label
1295
            // TRANSLATORS: number of chars in string should be near original
1296
            _("Name:                    "),
1297
            nullptr,
1298
            false);
1299
        mRenameListener.setDialog(mDialog);
1300
        mDialog->setText(mMapItem->getComment());
1301
        mDialog->setActionEventId("ok");
1302
        mDialog->addActionListener(&mRenameListener);
1303
    }
1304
    else if (link == "edit spell" && (mSpell != nullptr))
1305
    {
1306
        CREATEWIDGET(TextCommandEditor, mSpell);
1307
    }
1308
    else if (link == "addcomment" && !mName.empty())
1309
    {
1310
        TextDialog *const dialog = CREATEWIDGETR(TextDialog,
1311
            // TRANSLATORS: dialog caption
1312
            // TRANSLATORS: number of chars in string should be near original
1313
            _("Player comment            "),
1314
            // TRANSLATORS: label
1315
            // TRANSLATORS: number of chars in string should be near original
1316
            _("Comment:                      "),
1317
            nullptr,
1318
            false);
1319
        mPlayerListener.setDialog(dialog);
1320
        mPlayerListener.setNick(mName);
1321
        mPlayerListener.setType(mType);
1322
1323
        if (being != nullptr)
1324
        {
1325
            being->updateComment();
1326
            dialog->setText(being->getComment());
1327
        }
1328
        else
1329
        {
1330
            dialog->setText(Being::loadComment(mName,
1331
                static_cast<ActorTypeT>(mType)));
1332
        }
1333
        dialog->setActionEventId("ok");
1334
        dialog->addActionListener(&mPlayerListener);
1335
    }
1336
    else if (link == "guild-pos" && !mName.empty())
1337
    {
1338
        showChangePos(getX(), getY());
1339
        return;
1340
    }
1341
    else if (link == "clipboard copy")
1342
    {
1343
        if (mTextField != nullptr)
1344
            mTextField->handleCopy();
1345
    }
1346
    else if (link == "clipboard paste")
1347
    {
1348
        if (mTextField != nullptr)
1349
            mTextField->handlePaste();
1350
    }
1351
    else if (link == "gm" && !mName.empty())
1352
    {
1353
        showGMPopup(mName);
1354
        return;
1355
    }
1356
    else if (link == "mute" && !mName.empty())
1357
    {
1358
        showMuteCommands();
1359
        return;
1360
    }
1361
    else if (link == "show" && !mName.empty())
1362
    {
1363
        showPlayerMenu();
1364
        return;
1365
    }
1366
    else if (link == "window close" && (mCallerWindow != nullptr))
1367
    {
1368
        if (Widget::widgetExists(mCallerWindow))
1369
            mCallerWindow->close();
1370
    }
1371
    else if (link == "window unlock" && (mCallerWindow != nullptr))
1372
    {
1373
        if (Widget::widgetExists(mCallerWindow))
1374
            mCallerWindow->setSticky(false);
1375
    }
1376
    else if (link == "window lock" && (mCallerWindow != nullptr))
1377
    {
1378
        if (Widget::widgetExists(mCallerWindow))
1379
            mCallerWindow->setSticky(true);
1380
    }
1381
    else if (link == "join chat" && (being != nullptr))
1382
    {
1383
        const ChatObject *const chat = being->getChat();
1384
        if (chat != nullptr)
1385
            chatHandler->joinChat(chat, "");
1386
    }
1387
    else if (link == "craftmenu")
1388
    {
1389
        showCraftPopup();
1390
        return;
1391
    }
1392
    else if (link.compare(0, 10, "guild-pos-") == 0)
1393
    {
1394
        if (localPlayer != nullptr)
1395
        {
1396
            const int num = atoi(link.substr(10).c_str());
1397
            const Guild *const guild = localPlayer->getGuild();
1398
            if (guild != nullptr)
1399
            {
1400
                guildHandler->changeMemberPostion(
1401
                    guild->getMember(mName), num);
1402
            }
1403
        }
1404
    }
1405
    else if (link.compare(0, 7, "player_") == 0)
1406
    {
1407
        if (actorManager != nullptr)
1408
        {
1409
            mBeingId = fromInt(atoi(link.substr(7).c_str()), BeingId);
1410
            being = actorManager->findBeing(mBeingId);
1411
            if (being != nullptr)
1412
            {
1413
                showPopup(getX(), getY(), being);
1414
                return;
1415
            }
1416
        }
1417
    }
1418
    else if (link.compare(0, 10, "flooritem_") == 0)
1419
    {
1420
        if (actorManager != nullptr)
1421
        {
1422
            const BeingId id = fromInt(atoi(
1423
                link.substr(10).c_str()), BeingId);
1424
            if (id != BeingId_zero)
1425
            {
1426
                const FloorItem *const item = actorManager->findItem(id);
1427
                if (item != nullptr)
1428
                {
1429
                    mFloorItemId = item->getId();
1430
                    mItemId = item->getItemId();
1431
                    for (int f = 0; f < maxCards; f ++)
1432
                        mItemCards[f] = item->getCard(f);
1433
                    showPopup(getX(), getY(), item);
1434
                    return;
1435
                }
1436
            }
1437
        }
1438
    }
1439
    else if (link.compare(0, 12, "hide button_") == 0)
1440
    {
1441
        if (windowMenu != nullptr)
1442
            windowMenu->showButton(link.substr(12), Visible_false);
1443
    }
1444
    else if (link.compare(0, 12, "show button_") == 0)
1445
    {
1446
        if (windowMenu != nullptr)
1447
            windowMenu->showButton(link.substr(12), Visible_true);
1448
    }
1449
    else if (link.compare(0, 9, "hide bar_") == 0)
1450
    {
1451
        if (miniStatusWindow != nullptr)
1452
            miniStatusWindow->showBar(link.substr(9), Visible_false);
1453
    }
1454
    else if (link.compare(0, 9, "show bar_") == 0)
1455
    {
1456
        if (miniStatusWindow != nullptr)
1457
            miniStatusWindow->showBar(link.substr(9), Visible_true);
1458
    }
1459
    else if (link.compare(0, 12, "show window_") == 0)
1460
    {
1461
        const int id = atoi(link.substr(12).c_str());
1462
        if (id >= 0)
1463
            inputManager.executeAction(static_cast<InputActionT>(id));
1464
    }
1465
    else if (link.compare(0, 6, "mute_+") == 0)
1466
    {
1467
        if (being != nullptr)
1468
        {
1469
            const int time = atoi(link.substr(6).c_str());
1470
            adminHandler->mute(being, 1, time);
1471
        }
1472
    }
1473
    else if (link.compare(0, 6, "mute_-") == 0)
1474
    {
1475
        if (being != nullptr)
1476
        {
1477
            const int time = atoi(link.substr(6).c_str());
1478
            adminHandler->mute(being, 0, time);
1479
        }
1480
    }
1481
    else if (!link.empty() && link[0] == '/')
1482
    {
1483
        std::string cmd = link.substr(1);
1484
        replaceAll(cmd, "'NAME'", mName);
1485
        replaceAll(cmd, "'ENAME'", escapeString(mName));
1486
        replaceAll(cmd, "'EXTNAME'", mExtName);
1487
        replaceAll(cmd, "'EEXTNAME'", escapeString(mExtName));
1488
        replaceAll(cmd, "'X'", toString(mX));
1489
        replaceAll(cmd, "'Y'", toString(mY));
1490
        replaceAll(cmd, "'BEINGID'", toString(toInt(mBeingId, int)));
1491
        replaceAll(cmd, "'FLOORID'", toString(toInt(mFloorItemId, int)));
1492
        replaceAll(cmd, "'ITEMID'", toString(mItemId));
1493
        replaceAll(cmd, "'ITEMCOLOR'", toString(toInt(mItemColor, int)));
1494
        replaceAll(cmd, "'BEINGTYPEID'", toString(CAST_S32(mType)));
1495
        replaceAll(cmd, "'BEINGSUBTYPEID'", toString(CAST_S32(mSubType)));
1496
        replaceAll(cmd, "'PLAYER'", localPlayer->getName());
1497
        replaceAll(cmd, "'EPLAYER'", escapeString(localPlayer->getName()));
1498
        replaceAll(cmd, "'PLAYERX'", toString(localPlayer->getTileX()));
1499
        replaceAll(cmd, "'PLAYERY'", toString(localPlayer->getTileY()));
1500
        if (mItemIndex >= 0)
1501
            replaceAll(cmd, "'INVINDEX'", toString(mItemIndex));
1502
        else
1503
            replaceAll(cmd, "'INVINDEX'", "0");
1504
        if (mMapItem != nullptr)
1505
        {
1506
            replaceAll(cmd, "'MAPX'", toString(mMapItem->getX()));
1507
            replaceAll(cmd, "'MAPY'", toString(mMapItem->getY()));
1508
        }
1509
        else
1510
        {
1511
            replaceAll(cmd, "'MAPX'", toString(mX));
1512
            replaceAll(cmd, "'MAPY'", toString(mY));
1513
        }
1514
1515
        std::string cards;
1516
        for (int f = 0; f < maxCards; f ++)
1517
        {
1518
            const int id = mItemCards[f];
1519
            if (id != 0)
1520
            {
1521
                cards.append(",");
1522
                cards.append(toString(id));
1523
            }
1524
        }
1525
        replaceAll(cmd, "'CARDS'", cards);
1526
        replaceAll(cmd, "'ECARDS'", escapeString(cards));
1527
        if (actorManager != nullptr)
1528
        {
1529
            if (being == nullptr)
1530
            {
1531
                being = actorManager->findBeingByName(mName,
1532
                    ActorType::Player);
1533
            }
1534
        }
1535
        if (being != nullptr)
1536
            replaceAll(cmd, "'PARTY'", being->getPartyName());
1537
        else
1538
            replaceAll(cmd, "'PARTY'", "");
1539
1540
        const size_t pos = cmd.find(' ');
1541
        const std::string type(cmd, 0, pos);
1542
        std::string args(cmd, pos == std::string::npos ? cmd.size() : pos + 1);
1543
        args = trim(args);
1544
        inputManager.executeChatCommand(type, args, mTab);
1545
    }
1546
    // Unknown actions
1547
    else if (link != "cancel")
1548
    {
1549
        reportAlways("PopupMenu: Warning, unknown action '%s'", link.c_str());
1550
    }
1551
1552
    if (!mAllowCleanMenu)
1553
        return;
1554
1555
    setVisible(Visible_false);
1556
1557
    mBeingId = BeingId_zero;
1558
    mFloorItemId = BeingId_zero;
1559
    mItemId = 0;
1560
    mItemIndex = -1;
1561
    for (int f = 0; f < maxCards; f ++)
1562
        mItemCards[f] = 0;
1563
    mItemColor = ItemColor_one;
1564
    mMapItem = nullptr;
1565
    mTab = nullptr;
1566
    mSpell = nullptr;
1567
    mCallerWindow = nullptr;
1568
    mDialog = nullptr;
1569
    mButton = nullptr;
1570
    mName.clear();
1571
    mExtName.clear();
1572
    mTextField = nullptr;
1573
    mType = ActorType::Unknown;
1574
    mSubType = BeingTypeId_zero;
1575
    mX = 0;
1576
    mY = 0;
1577
}
1578
1579
void PopupMenu::showPopup(Window *const parent,
1580
                          const int x, const int y,
1581
                          const Item *const item,
1582
                          const InventoryTypeT type)
1583
{
1584
    if (item == nullptr)
1585
        return;
1586
1587
    initPopup();
1588
    mItemId = item->getId();
1589
    mItemIndex = item->getInvIndex();
1590
    for (int f = 0; f < maxCards; f ++)
1591
        mItemCards[f] = item->getCard(f);
1592
    mItemColor = item->getColor();
1593
    mCallerWindow = parent;
1594
    mX = x;
1595
    mY = y;
1596
    mName.clear();
1597
    mExtName.clear();
1598
    mBrowserBox->clearRows();
1599
1600
    const int cnt = item->getQuantity();
1601
    const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1602
1603
    switch (type)
1604
    {
1605
        case InventoryType::Inventory:
1606
            if (tradeWindow != nullptr &&
1607
                tradeWindow->isWindowVisible() &&
1608
                !isProtected)
1609
            {
1610
                // TRANSLATORS: popup menu item
1611
                // TRANSLATORS: add item to trade
1612
                mBrowserBox->addRow("/addtrade 'INVINDEX'", _("Add to trade"));
1613
                if (cnt > 1)
1614
                {
1615
                    if (cnt > 10)
1616
                    {
1617
                        mBrowserBox->addRow("/addtrade 'INVINDEX' 10",
1618
                            // TRANSLATORS: popup menu item
1619
                            // TRANSLATORS: add 10 item amount to trade
1620
                            _("Add to trade 10"));
1621
                    }
1622
                    mBrowserBox->addRow("/addtrade 'INVINDEX' /",
1623
                        // TRANSLATORS: popup menu item
1624
                        // TRANSLATORS: add half item amount to trade
1625
                        _("Add to trade half"));
1626
                    mBrowserBox->addRow("/addtrade 'INVINDEX' -1",
1627
                        // TRANSLATORS: popup menu item
1628
                        // TRANSLATORS: add all amount except one item to trade
1629
                        _("Add to trade all-1"));
1630
                    mBrowserBox->addRow("/addtrade 'INVINDEX' all",
1631
                        // TRANSLATORS: popup menu item
1632
                        // TRANSLATORS: add all amount item to trade
1633
                        _("Add to trade all"));
1634
                }
1635
                mBrowserBox->addSeparator("##3---");
1636
            }
1637
            if (InventoryWindow::isStorageActive())
1638
            {
1639
                // TRANSLATORS: popup menu item
1640
                // TRANSLATORS: add item to storage
1641
                mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1642
                if (cnt > 1)
1643
                {
1644
                    if (cnt > 10)
1645
                    {
1646
                        mBrowserBox->addRow("/invtostorage 'INVINDEX' 10",
1647
                            // TRANSLATORS: popup menu item
1648
                            // TRANSLATORS: add 10 item amount to storage
1649
                            _("Store 10"));
1650
                    }
1651
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' /",
1652
                        // TRANSLATORS: popup menu item
1653
                        // TRANSLATORS: add half item amount to storage
1654
                        _("Store half"));
1655
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' -1",
1656
                        // TRANSLATORS: popup menu item
1657
                        // TRANSLATORS: add all except one item to storage
1658
                        _("Store all-1"));
1659
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' all",
1660
                        // TRANSLATORS: popup menu item
1661
                        // TRANSLATORS: add all item amount to storage
1662
                        _("Store all"));
1663
                }
1664
                mBrowserBox->addSeparator("##3---");
1665
            }
1666
            if (npcHandler != nullptr)
1667
            {
1668
                NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
1669
                if ((dialog != nullptr) &&
1670
                    dialog->getInputState() == NpcInputState::ITEM_CRAFT)
1671
                {
1672
                    mBrowserBox->addRow("craftmenu",
1673
                        // TRANSLATORS: popup menu item
1674
                        // TRANSLATORS: sub menu for craft
1675
                        _("Move to craft..."));
1676
                }
1677
            }
1678
            addItemMenu(item, InventoryType::Inventory);
1679
            addDrop(item, isProtected);
1680
            break;
1681
1682
        case InventoryType::Storage:
1683
            // TRANSLATORS: popup menu item
1684
            // TRANSLATORS: get item from storage
1685
            mBrowserBox->addRow("/storagetoinv 'INVINDEX'", _("Retrieve"));
1686
            if (cnt > 1)
1687
            {
1688
                if (cnt > 10)
1689
                {
1690
                    mBrowserBox->addRow("/storagetoinv 'INVINDEX' 10",
1691
                        // TRANSLATORS: popup menu item
1692
                        // TRANSLATORS: get 10 item amount from storage
1693
                        _("Retrieve 10"));
1694
                }
1695
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' /",
1696
                    // TRANSLATORS: popup menu item
1697
                    // TRANSLATORS: get half item amount from storage
1698
                    _("Retrieve half"));
1699
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' -1",
1700
                    // TRANSLATORS: popup menu item
1701
                    // TRANSLATORS: get all except one item amount from storage
1702
                    _("Retrieve all-1"));
1703
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' all",
1704
                    // TRANSLATORS: popup menu item
1705
                    // TRANSLATORS: get all item amount from storage
1706
                    _("Retrieve all"));
1707
                mBrowserBox->addSeparator("##3---");
1708
            }
1709
            addItemMenu(item, InventoryType::Storage);
1710
            break;
1711
        case InventoryType::Cart:
1712
            addItemMenu(item, InventoryType::Cart);
1713
            break;
1714
1715
        case InventoryType::Trade:
1716
        case InventoryType::Npc:
1717
        case InventoryType::Vending:
1718
        case InventoryType::MailEdit:
1719
        case InventoryType::MailView:
1720
        case InventoryType::Craft:
1721
        case InventoryType::TypeEnd:
1722
        default:
1723
            break;
1724
    }
1725
1726
1727
    addProtection();
1728
    if (config.getBoolValue("enablePickupFilter"))
1729
    {
1730
        mName = item->getName();
1731
        mExtName = mName;
1732
        mBrowserBox->addSeparator("##3---");
1733
        addPickupFilter(mName);
1734
    }
1735
    addGmCommands();
1736
    // TRANSLATORS: popup menu item
1737
    // TRANSLATORS: add item name to chat
1738
    mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1739
    mBrowserBox->addSeparator("##3---");
1740
    // TRANSLATORS: popup menu item
1741
    // TRANSLATORS: close menu
1742
    mBrowserBox->addRow("cancel", _("Cancel"));
1743
1744
    showPopup(x, y);
1745
}
1746
1747
void PopupMenu::showItemPopup(const int x, const int y,
1748
                              const int itemId,
1749
                              const ItemColor color)
1750
{
1751
    const Inventory *const inv = PlayerInfo::getInventory();
1752
    if (inv == nullptr)
1753
        return;
1754
1755
    Item *const item = inv->findItem(itemId, color);
1756
    if (item != nullptr)
1757
    {
1758
        showItemPopup(x, y, item);
1759
    }
1760
    else
1761
    {
1762
        initPopup();
1763
        mItemId = itemId;
1764
        mItemIndex = -1;
1765
        mItemColor = color;
1766
        for (int f = 0; f < maxCards; f ++)
1767
            mItemCards[f] = 0;
1768
        mX = x;
1769
        mY = y;
1770
        mBrowserBox->clearRows();
1771
1772
        if (!PlayerInfo::isItemProtected(mItemId))
1773
        {
1774
            // TRANSLATORS: popup menu item
1775
            // TRANSLATORS: use item
1776
            mBrowserBox->addRow("/use 'ITEMID'", _("Use"));
1777
        }
1778
        addProtection();
1779
        addGmCommands();
1780
        mBrowserBox->addSeparator("##3---");
1781
        // TRANSLATORS: popup menu item
1782
        // TRANSLATORS: close menu
1783
        mBrowserBox->addRow("cancel", _("Cancel"));
1784
1785
        showPopup(x, y);
1786
    }
1787
}
1788
1789
void PopupMenu::showItemPopup(const int x, const int y,
1790
                              const Item *const item)
1791
{
1792
    initPopup();
1793
    mX = x;
1794
    mY = y;
1795
    if (item != nullptr)
1796
    {
1797
        mItemId = item->getId();
1798
        mItemColor = item->getColor();
1799
        mItemIndex = item->getInvIndex();
1800
        for (int f = 0; f < maxCards; f ++)
1801
            mItemCards[f] = item->getCard(f);
1802
    }
1803
    else
1804
    {
1805
        mItemId = 0;
1806
        mItemColor = ItemColor_one;
1807
        mItemIndex = -1;
1808
        for (int f = 0; f < maxCards; f ++)
1809
            mItemCards[f] = 0;
1810
    }
1811
    mName.clear();
1812
    mExtName.clear();
1813
    mBrowserBox->clearRows();
1814
1815
    if (item != nullptr)
1816
    {
1817
        const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1818
        addUse(item);
1819
        addDrop(item, isProtected);
1820
        if (InventoryWindow::isStorageActive())
1821
        {
1822
            // TRANSLATORS: popup menu item
1823
            // TRANSLATORS: add item to storage
1824
            mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1825
        }
1826
        // TRANSLATORS: popup menu item
1827
        // TRANSLATORS: add item name to chat
1828
        mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1829
1830
        if (config.getBoolValue("enablePickupFilter"))
1831
        {
1832
            mName = item->getName();
1833
            mExtName = mName;
1834
            mBrowserBox->addSeparator("##3---");
1835
            addPickupFilter(mName);
1836
        }
1837
    }
1838
    addProtection();
1839
    addGmCommands();
1840
    mBrowserBox->addSeparator("##3---");
1841
    // TRANSLATORS: popup menu item
1842
    // TRANSLATORS: close menu
1843
    mBrowserBox->addRow("cancel", _("Cancel"));
1844
1845
    showPopup(x, y);
1846
}
1847
1848
void PopupMenu::showDropPopup(const int x,
1849
                              const int y,
1850
                              const Item *const item)
1851
{
1852
    initPopup();
1853
    mX = x;
1854
    mY = y;
1855
    mName.clear();
1856
    mExtName.clear();
1857
    mBrowserBox->clearRows();
1858
1859
    if (item != nullptr)
1860
    {
1861
        mItemId = item->getId();
1862
        mItemColor = item->getColor();
1863
        mItemIndex = item->getInvIndex();
1864
        for (int f = 0; f < maxCards; f ++)
1865
            mItemCards[f] = item->getCard(f);
1866
        const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1867
        addUse(item);
1868
        addDrop(item, isProtected);
1869
        if (InventoryWindow::isStorageActive())
1870
        {
1871
            // TRANSLATORS: popup menu item
1872
            // TRANSLATORS: add item to storage
1873
            mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1874
        }
1875
        addProtection();
1876
        // TRANSLATORS: popup menu item
1877
        // TRANSLATORS: add item name to chat
1878
        mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1879
        if (config.getBoolValue("enablePickupFilter"))
1880
        {
1881
            mName = item->getName();
1882
            mExtName = mName;
1883
            mBrowserBox->addSeparator("##3---");
1884
            addPickupFilter(mName);
1885
        }
1886
    }
1887
    addGmCommands();
1888
    mBrowserBox->addSeparator("##3---");
1889
    // TRANSLATORS: popup menu item
1890
    mBrowserBox->addRow("/cleardrops", _("Clear drop window"));
1891
    mBrowserBox->addSeparator("##3---");
1892
    // TRANSLATORS: popup menu item
1893
    // TRANSLATORS: close menu
1894
    mBrowserBox->addRow("cancel", _("Cancel"));
1895
1896
    showPopup(x, y);
1897
}
1898
1899
void PopupMenu::showPopup(const int x, const int y, Button *const button)
1900
{
1901
    if ((button == nullptr) || (windowMenu == nullptr))
1902
        return;
1903
1904
    initPopup();
1905
    mButton = button;
1906
    mX = x;
1907
    mY = y;
1908
1909
    mBrowserBox->clearRows();
1910
    STD_VECTOR<Button *> names = windowMenu->getButtons();
1911
    for (STD_VECTOR<Button *>::const_iterator it = names.begin(),
1912
         it_end = names.end(); it != it_end; ++ it)
1913
    {
1914
        const Button *const btn = *it;
1915
        if ((btn == nullptr) || btn->getActionEventId() == "SET")
1916
            continue;
1917
1918
        if (btn->mVisible == Visible_true)
1919
        {
1920
            mBrowserBox->addRow(strprintf("@@hide button_%s|%s %s (%s)@@",
1921
                // TRANSLATORS: popup menu item
1922
                btn->getActionEventId().c_str(), _("Hide"),
1923
                btn->getDescription().c_str(), btn->getCaption().c_str()),
1924
                false);
1925
        }
1926
        else
1927
        {
1928
            mBrowserBox->addRow(strprintf("@@show button_%s|%s %s (%s)@@",
1929
                // TRANSLATORS: popup menu item
1930
                btn->getActionEventId().c_str(), _("Show"),
1931
                btn->getDescription().c_str(), btn->getCaption().c_str()),
1932
                false);
1933
        }
1934
    }
1935
    mBrowserBox->addSeparator("##3---");
1936
    // TRANSLATORS: popup menu item
1937
    // TRANSLATORS: close menu
1938
    mBrowserBox->addRow("cancel", _("Cancel"));
1939
1940
    showPopup(x, y);
1941
}
1942
1943
void PopupMenu::showPopup(const int x, const int y, const ProgressBar *const b)
1944
{
1945
    if ((b == nullptr) || (miniStatusWindow == nullptr))
1946
        return;
1947
1948
    initPopup();
1949
    mName = b->text();
1950
    mExtName = mName;
1951
    mX = x;
1952
    mY = y;
1953
1954
    mBrowserBox->clearRows();
1955
    STD_VECTOR <ProgressBar*> bars = miniStatusWindow->getBars();
1956
    ProgressBar *onlyBar = nullptr;
1957
    int cnt = 0;
1958
1959
    // search for alone visible bar
1960
    for (STD_VECTOR <ProgressBar*>::const_iterator it = bars.begin(),
1961
         it_end = bars.end(); it != it_end; ++it)
1962
    {
1963
        ProgressBar *const bar = *it;
1964
        if (bar == nullptr)
1965
            continue;
1966
1967
        if (bar->mVisible == Visible_true)
1968
        {
1969
            cnt ++;
1970
            onlyBar = bar;
1971
        }
1972
    }
1973
    if (cnt > 1)
1974
        onlyBar = nullptr;
1975
1976
    for (STD_VECTOR <ProgressBar*>::const_iterator it = bars.begin(),
1977
         it_end = bars.end(); it != it_end; ++it)
1978
    {
1979
        ProgressBar *const bar = *it;
1980
        if ((bar == nullptr) || bar == onlyBar)
1981
            continue;
1982
1983
        if (bar->mVisible == Visible_true)
1984
        {
1985
            mBrowserBox->addRow(strprintf("@@hide bar_%s|%s %[email protected]@",
1986
                // TRANSLATORS: popup menu item
1987
                bar->getActionEventId().c_str(), _("Hide"),
1988
                bar->getId().c_str()),
1989
                false);
1990
        }
1991
        else
1992
        {
1993
            mBrowserBox->addRow(strprintf("@@show bar_%s|%s %[email protected]@",
1994
                // TRANSLATORS: popup menu item
1995
                bar->getActionEventId().c_str(), _("Show"),
1996
                bar->getId().c_str()),
1997
                false);
1998
        }
1999
    }
2000
2001
    mBrowserBox->addSeparator("##3---");
2002
    // TRANSLATORS: popup menu item
2003
    mBrowserBox->addRow("/yellowbar", _("Open yellow bar settings"));
2004
    // TRANSLATORS: popup menu item
2005
    mBrowserBox->addRow("/resetmodifiers", _("Reset yellow bar"));
2006
    mBrowserBox->addSeparator("##3---");
2007
    // TRANSLATORS: popup menu item
2008
    // TRANSLATORS: copy status to chat
2009
    mBrowserBox->addRow("/bartochat 'NAME'", _("Copy to chat"));
2010
    // TRANSLATORS: popup menu item
2011
    // TRANSLATORS: close menu
2012
    mBrowserBox->addRow("cancel", _("Cancel"));
2013
2014
    showPopup(x, y);
2015
}
2016
2017
void PopupMenu::showAttackMonsterPopup(const int x, const int y,
2018
                                       const std::string &name,
2019
                                       const int type)
2020
{
2021
    if ((localPlayer == nullptr) || (actorManager == nullptr))
2022
        return;
2023
2024
    initPopup();
2025
    mName = name;
2026
    mExtName = name;
2027
    mType = ActorType::Monster;
2028
    mSubType = BeingTypeId_zero;
2029
    mX = x;
2030
    mY = y;
2031
2032
    mBrowserBox->clearRows();
2033
2034
    if (name.empty())
2035
    {
2036
        // TRANSLATORS: popup menu header
2037
        mBrowserBox->addRow(_("(default)"), false);
2038
    }
2039
    else
2040
    {
2041
        mBrowserBox->addRow(name, false);
2042
    }
2043
    switch (type)
2044
    {
2045
        case MapItemType::ATTACK:
2046
        {
2047
            const int idx = actorManager->getAttackMobIndex(name);
2048
            const int size = actorManager->getAttackMobsSize();
2049
            if (idx > 0)
2050
            {
2051
                // TRANSLATORS: popup menu item
2052
                // TRANSLATORS: move attack target up
2053
                mBrowserBox->addRow("/moveattackup 'NAME'", _("Move up"));
2054
            }
2055
            if (idx + 1 < size)
2056
            {
2057
                // TRANSLATORS: popup menu item
2058
                // TRANSLATORS: move attack target down
2059
                mBrowserBox->addRow("/moveattackdown 'NAME'", _("Move down"));
2060
            }
2061
            break;
2062
        }
2063
        case MapItemType::PRIORITY:
2064
        {
2065
            const int idx = actorManager->
2066
                getPriorityAttackMobIndex(name);
2067
            const int size = actorManager->getPriorityAttackMobsSize();
2068
            if (idx > 0)
2069
            {
2070
                mBrowserBox->addRow("/movepriorityattackup 'NAME'",
2071
                    // TRANSLATORS: popup menu item
2072
                    // TRANSLATORS: move attack target up
2073
                    _("Move up"));
2074
            }
2075
            if (idx + 1 < size)
2076
            {
2077
                mBrowserBox->addRow("/movepriorityattackdown 'NAME'",
2078
                    // TRANSLATORS: popup menu item
2079
                    // TRANSLATORS: move attack target down
2080
                    _("Move down"));
2081
            }
2082
            break;
2083
        }
2084
        case MapItemType::IGNORE_:
2085
            break;
2086
        default:
2087
            break;
2088
    }
2089
2090
    // TRANSLATORS: popup menu item
2091
    // TRANSLATORS: remove attack target
2092
    mBrowserBox->addRow("/removeattack 'NAME'", _("Remove"));
2093
    mBrowserBox->addSeparator("##3---");
2094
    // TRANSLATORS: popup menu item
2095
    // TRANSLATORS: close menu
2096
    mBrowserBox->addRow("cancel", _("Cancel"));
2097
2098
    showPopup(x, y);
2099
}
2100
2101
void PopupMenu::showPickupItemPopup(const int x, const int y,
2102
                                    const std::string &name)
2103
{
2104
    if ((localPlayer == nullptr) || (actorManager == nullptr))
2105
        return;
2106
2107
    initPopup();
2108
    mName = name;
2109
    mExtName = name;
2110
    mType = ActorType::FloorItem;
2111
    mSubType = BeingTypeId_zero;
2112
    mX = x;
2113
    mY = y;
2114
2115
    mBrowserBox->clearRows();
2116
2117
    if (name.empty())
2118
    {
2119
        // TRANSLATORS: popup menu header
2120
        mBrowserBox->addRow(_("(default)"), false);
2121
    }
2122
    else
2123
    {
2124
        mBrowserBox->addRow(name, false);
2125
    }
2126
2127
    // TRANSLATORS: popup menu item
2128
    // TRANSLATORS: remove item from pickup filter
2129
    mBrowserBox->addRow("/removepickup 'NAME'", _("Remove"));
2130
    mBrowserBox->addSeparator("##3---");
2131
    // TRANSLATORS: popup menu item
2132
    // TRANSLATORS: close menu
2133
    mBrowserBox->addRow("cancel", _("Cancel"));
2134
2135
    showPopup(x, y);
2136
}
2137
2138
void PopupMenu::showUndressPopup(const int x, const int y,
2139
                                 const Being *const being,
2140
                                 const Item *const item)
2141
{
2142
    if ((being == nullptr) || (item == nullptr))
2143
        return;
2144
2145
    initPopup();
2146
    mBeingId = being->getId();
2147
    mItemId = item->getId();
2148
    mItemColor = item->getColor();
2149
    mItemIndex = item->getInvIndex();
2150
    for (int f = 0; f < maxCards; f ++)
2151
        mItemCards[f] = item->getCard(f);
2152
    mX = x;
2153
    mY = y;
2154
2155
    mBrowserBox->clearRows();
2156
2157
    // TRANSLATORS: popup menu item
2158
    // TRANSLATORS: undress item from player
2159
    mBrowserBox->addRow("/undress :'BEINGID' 'ITEMID'", _("Undress"));
2160
    // TRANSLATORS: popup menu item
2161
    // TRANSLATORS: add item name to chat
2162
    mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
2163
    addGmCommands();
2164
    mBrowserBox->addSeparator("##3---");
2165
    // TRANSLATORS: popup menu item
2166
    // TRANSLATORS: close menu
2167
    mBrowserBox->addRow("cancel", _("Cancel"));
2168
2169
    showPopup(x, y);
2170
}
2171
2172
void PopupMenu::showTextFieldPopup(TextField *const input)
2173
{
2174
    initPopup();
2175
    setMousePos();
2176
    mTextField = input;
2177
2178
    mBrowserBox->clearRows();
2179
2180
    // TRANSLATORS: popup menu item
2181
    // TRANSLATORS: copy text to clipboard
2182
    mBrowserBox->addRow("clipboard copy", _("Copy"));
2183
    // TRANSLATORS: popup menu item
2184
    // TRANSLATORS: paste text from clipboard
2185
    mBrowserBox->addRow("clipboard paste", _("Paste"));
2186
    mBrowserBox->addSeparator("##3---");
2187
    // TRANSLATORS: popup menu item
2188
    // TRANSLATORS: close menu
2189
    mBrowserBox->addRow("cancel", _("Cancel"));
2190
2191
    showPopup(mX, mY);
2192
}
2193
2194
void PopupMenu::showLinkPopup(const std::string &link)
2195
{
2196
    initPopup();
2197
    setMousePos();
2198
    mName = link;
2199
    mExtName = link;
2200
2201
    mBrowserBox->clearRows();
2202
2203
    // TRANSLATORS: popup menu item
2204
    // TRANSLATORS: open link in browser
2205
    mBrowserBox->addRow("/open 'NAME'", _("Open link"));
2206
    // TRANSLATORS: popup menu item
2207
    // TRANSLATORS: copy link to clipboard
2208
    mBrowserBox->addRow("/clipboardcopy 'NAME'", _("Copy to clipboard"));
2209
    mBrowserBox->addSeparator("##3---");
2210
    // TRANSLATORS: popup menu item
2211
    // TRANSLATORS: close menu
2212
    mBrowserBox->addRow("cancel", _("Cancel"));
2213
2214
    showPopup(mX, mY);
2215
}
2216
2217
void PopupMenu::showWindowsPopup()
2218
{
2219
    initPopup();
2220
    setMousePos();
2221
    mBrowserBox->clearRows();
2222
    const STD_VECTOR<ButtonText*> &names = windowMenu->getButtonTexts();
2223
    // TRANSLATORS: popup menu header
2224
    mBrowserBox->addRow(_("Show window"), false);
2225
2226
    FOR_EACH (STD_VECTOR<ButtonText*>::const_iterator, it, names)
2227
    {
2228
        const ButtonText *const btn = *it;
2229
        if (btn == nullptr)
2230
            continue;
2231
2232
        mBrowserBox->addRow(strprintf("show window_%d",
2233
            CAST_S32(btn->key)),
2234
            btn->text.c_str());
2235
    }
2236
    mBrowserBox->addSeparator("##3---");
2237
    // TRANSLATORS: popup menu item
2238
    // TRANSLATORS: close menu
2239
    mBrowserBox->addRow("cancel", _("Cancel"));
2240
2241
    showPopup(mX, mY);
2242
}
2243
2244
void PopupMenu::showNpcDialogPopup(const BeingId npcId,
2245
                                   const int x, const int y)
2246
{
2247
    initPopup();
2248
    mBeingId = npcId;
2249
    mX = x;
2250
    mY = y;
2251
    mBrowserBox->clearRows();
2252
    // TRANSLATORS: popup menu item
2253
    // TRANSLATORS: copy npc text to clipboard
2254
    mBrowserBox->addRow("/npcclipboard 'X' 'Y'", _("Copy to clipboard"));
2255
    mBrowserBox->addSeparator("##3---");
2256
    // TRANSLATORS: popup menu item
2257
    // TRANSLATORS: close menu
2258
    mBrowserBox->addRow("cancel", _("Cancel"));
2259
2260
    showPopup(x, y);
2261
}
2262
2263
void PopupMenu::showSkillPopup(const SkillInfo *const info)
2264
{
2265
    if (info == nullptr)
2266
        return;
2267
2268
    initPopup();
2269
    setMousePos();
2270
2271
    // using mItemId as skill id
2272
    mItemId = info->id;
2273
    // using mItemIndex as skill level
2274
    mItemIndex = info->level;
2275
    mBrowserBox->clearRows();
2276
2277
    // TRANSLATORS: popup menu header
2278
    mBrowserBox->addRow(_("Skill"), false);
2279
    mBrowserBox->addRow("/addskillshortcut 'ITEMID'",
2280
        // TRANSLATORS: popup menu item
2281
        // TRANSLATORS: add skill to shortcurs tab
2282
        _("Add skill shortcut"));
2283
    mBrowserBox->addSeparator("##3---");
2284
    mBrowserBox->addRow("/showskilllevels 'ITEMID'",
2285
        // TRANSLATORS: popup menu item
2286
        // TRANSLATORS: set skill level
2287
        _("Skill level..."));
2288
    mBrowserBox->addRow("/showskilltypes 'ITEMID'",
2289
        // TRANSLATORS: popup menu item
2290
        // TRANSLATORS: set skill cast type
2291
        _("Skill cast type..."));
2292
    mBrowserBox->addRow("/showskilloffsetx 'ITEMID'",
2293
        // TRANSLATORS: popup menu item
2294
        // TRANSLATORS: set skill cast offset by x
2295
        _("Skill offset by x..."));
2296
    mBrowserBox->addRow("/showskilloffsety 'ITEMID'",
2297
        // TRANSLATORS: popup menu item
2298
        // TRANSLATORS: set skill cast offset by y
2299
        _("Skill offset by y..."));
2300
    // TRANSLATORS: popup menu item
2301
    // TRANSLATORS: close menu
2302
    mBrowserBox->addRow("cancel", _("Cancel"));
2303
2304
    showPopup(mX, mY);
2305
}
2306
2307
void PopupMenu::showSkillOffsetPopup(const SkillInfo *const info,
2308
                                     const bool isOffsetX)
2309
{
2310
    if (info == nullptr)
2311
        return;
2312
2313
    initPopup();
2314
    setMousePos2();
2315
2316
    // using mItemId as skill id
2317
    mItemId = info->id;
2318
    // using mItemIndex as skill level
2319
    mItemIndex = info->level;
2320
    mBrowserBox->clearRows();
2321
    char letter = ' ';
2322
2323
    if (isOffsetX)
2324
    {
2325
        // TRANSLATORS: popup menu header
2326
        mBrowserBox->addRow(_("Skill cast offset by x"), false);
2327
        letter = 'x';
2328
    }
2329
    else
2330
    {
2331
        // TRANSLATORS: popup menu header
2332
        mBrowserBox->addRow(_("Skill cast offset by y"), false);
2333
        letter = 'y';
2334
    }
2335
    for (int f = -9; f <= 9; f ++)
2336
    {
2337
        const std::string command = strprintf(
2338
            "/setskilloffset%c 'ITEMID' %d", letter, f);
2339
        if (f == 0)
2340
        {
2341
            mBrowserBox->addRow(command,
2342
                strprintf("%d", f).c_str());
2343
        }
2344
        else
2345
        {
2346
            mBrowserBox->addRow(command,
2347
                strprintf("%+d", f).c_str());
2348
        }
2349
    }
2350
    // TRANSLATORS: popup menu item
2351
    // TRANSLATORS: close menu
2352
    mBrowserBox->addRow("cancel", _("Cancel"));
2353
    showPopup(mX, mY);
2354
}
2355
2356
void PopupMenu::showSkillLevelPopup(const SkillInfo *const info)
2357
{
2358
    if (info == nullptr)
2359
        return;
2360
2361
    initPopup();
2362
    setMousePos2();
2363
2364
    // using mItemId as skill id
2365
    mItemId = info->id;
2366
    // using mItemIndex as skill level
2367
    mItemIndex = info->level;
2368
2369
    for (int f = 0; f < maxCards; f ++)
2370
        mItemCards[f] = 0;
2371
    mBrowserBox->clearRows();
2372
    // TRANSLATORS: popup menu item
2373
    // TRANSLATORS: skill level header
2374
    mBrowserBox->addRow(_("Select skill level"), false);
2375
    for (int f = 1; f <= mItemIndex; f ++)
2376
    {
2377
        mBrowserBox->addRow(strprintf("/selectskilllevel %d %d", mItemId, f),
2378
            // TRANSLATORS: popup menu item
2379
            // TRANSLATORS: skill level
2380
            strprintf(_("Level: %d"), f).c_str());
2381
    }
2382
    mBrowserBox->addRow(strprintf("/selectskilllevel %d 0", mItemId),
2383
        // TRANSLATORS: popup menu item
2384
        // TRANSLATORS: skill level
2385
        _("Max level"));
2386
    mBrowserBox->addSeparator("##3---");
2387
    // TRANSLATORS: popup menu item
2388
    // TRANSLATORS: close menu
2389
    mBrowserBox->addRow("cancel", _("Cancel"));
2390
2391
    showPopup(mX, mY);
2392
}
2393
2394
void PopupMenu::showSkillTypePopup(const SkillInfo *const info)
2395
{
2396
    if (info == nullptr)
2397
        return;
2398
2399
    initPopup();
2400
    setMousePos2();
2401
2402
    // using mItemId as skill id
2403
    mItemId = info->id;
2404
    // using mItemIndex as skill level
2405
    mItemIndex = info->level;
2406
2407
    for (int f = 0; f < maxCards; f ++)
2408
        mItemCards[f] = 0;
2409
    mBrowserBox->clearRows();
2410
2411
    // TRANSLATORS: popup menu item
2412
    // TRANSLATORS: skill cast type header
2413
    mBrowserBox->addRow(_("Select skill cast type"), false);
2414
    mBrowserBox->addRow(strprintf("/selectskilltype %d 0", mItemId),
2415
        // TRANSLATORS: popup menu item
2416
        // TRANSLATORS: skill cast type
2417
        _("Default"));
2418
    mBrowserBox->addRow(strprintf("/selectskilltype %d 1", mItemId),
2419
        // TRANSLATORS: popup menu item
2420
        // TRANSLATORS: skill cast type
2421
        _("Target"));
2422
    mBrowserBox->addRow(strprintf("/selectskilltype %d 2", mItemId),
2423
        // TRANSLATORS: popup menu item
2424
        // TRANSLATORS: skill cast type
2425
        _("Mouse position"));
2426
    mBrowserBox->addRow(strprintf("/selectskilltype %d 3", mItemId),
2427
        // TRANSLATORS: popup menu item
2428
        // TRANSLATORS: skill cast type
2429
        _("Self"));
2430
    mBrowserBox->addSeparator("##3---");
2431
    // TRANSLATORS: popup menu item
2432
    // TRANSLATORS: close menu
2433
    mBrowserBox->addRow("cancel", _("Cancel"));
2434
2435
    showPopup(mX, mY);
2436
}
2437
2438
void PopupMenu::showPopup(int x, int y)
2439
{
2440
    PopupManager::hideItemPopup();
2441
    const int pad2 = 2 * mPadding;
2442
    mBrowserBox->setPosition(mPadding, mPadding);
2443
    mScrollArea->setPosition(mPadding, mPadding);
2444
    mBrowserBox->updateHeight();
2445
    // add padding to initial size before draw browserbox
2446
    int height = mBrowserBox->getHeight();
2447
    if (height + pad2 >= mainGraphics->getHeight())
2448
    {
2449
        height = mainGraphics->getHeight() - pad2;
2450
        mBrowserBox->setWidth(mBrowserBox->getWidth() + 5);
2451
        mScrollArea->setWidth(mBrowserBox->getWidth() + pad2 + 10);
2452
        setContentSize(mBrowserBox->getWidth() + pad2 + 20,
2453
            height + pad2);
2454
    }
2455
    else
2456
    {
2457
        mBrowserBox->setWidth(mBrowserBox->getWidth());
2458
        mScrollArea->setWidth(mBrowserBox->getWidth() + pad2);
2459
        setContentSize(mBrowserBox->getWidth() + pad2,
2460
            height + pad2);
2461
    }
2462
    if (mainGraphics->mWidth < (x + getWidth() + 5))
2463
        x = mainGraphics->mWidth - getWidth();
2464
    if (mainGraphics->mHeight < (y + getHeight() + 5))
2465
        y = mainGraphics->mHeight - getHeight();
2466
    mScrollArea->setHeight(height);
2467
    setPosition(x, y);
2468
    setVisible(Visible_true);
2469
    requestMoveToTop();
2470
    mAllowCleanMenu = false;
2471
}
2472
2473
void PopupMenu::addNormalRelations()
2474
{
2475
    // TRANSLATORS: popup menu item
2476
    // TRANSLATORS: add player to disregarded list
2477
    mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2478
    // TRANSLATORS: popup menu item
2479
    // TRANSLATORS: add player to ignore list
2480
    mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2481
    // TRANSLATORS: popup menu item
2482
    // TRANSLATORS: add player to black list
2483
    mBrowserBox->addRow("/blacklist 'NAME'", _("Black list"));
2484
    // TRANSLATORS: popup menu item
2485
    // TRANSLATORS: add player to enemy list
2486
    mBrowserBox->addRow("/enemy 'NAME'", _("Set as enemy"));
2487
    // TRANSLATORS: popup menu item
2488
    // TRANSLATORS: add player to erased list
2489
    mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2490
}
2491
2492
void PopupMenu::addPlayerRelation(const std::string &name)
2493
{
2494
    switch (playerRelations.getRelation(name))
2495
    {
2496
        case Relation::NEUTRAL:
2497
            // TRANSLATORS: popup menu item
2498
            // TRANSLATORS: add player to friends list
2499
            mBrowserBox->addRow("/friend 'NAME'", _("Be friend"));
2500
            addNormalRelations();
2501
            break;
2502
2503
        case Relation::FRIEND:
2504
            addNormalRelations();
2505
            break;
2506
2507
        case Relation::BLACKLISTED:
2508
            // TRANSLATORS: popup menu item
2509
            // TRANSLATORS: remove player from ignore list
2510
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2511
            // TRANSLATORS: popup menu item
2512
            // TRANSLATORS: add player to disregarded list
2513
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2514
            // TRANSLATORS: popup menu item
2515
            // TRANSLATORS: add player to ignore list
2516
            mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2517
            // TRANSLATORS: popup menu item
2518
            // TRANSLATORS: add player to enemy list
2519
            mBrowserBox->addRow("/enemy 'NAME'", _("Set as enemy"));
2520
            // TRANSLATORS: popup menu item
2521
            // TRANSLATORS: add player to erased list
2522
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2523
            break;
2524
2525
        case Relation::DISREGARDED:
2526
            // TRANSLATORS: popup menu item
2527
            // TRANSLATORS: remove player from ignore list
2528
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2529
            // TRANSLATORS: popup menu item
2530
            // TRANSLATORS: add player to completle ignore list
2531
            mBrowserBox->addRow("/ignore 'NAME'", _("Completely ignore"));
2532
            // TRANSLATORS: popup menu item
2533
            // TRANSLATORS: add player to erased list
2534
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2535
            break;
2536
2537
        case Relation::IGNORED:
2538
            // TRANSLATORS: popup menu item
2539
            // TRANSLATORS: remove player from ignore list
2540
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2541
            // TRANSLATORS: popup menu item
2542
            // TRANSLATORS: add player to erased list
2543
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2544
            break;
2545
2546
        case Relation::ENEMY2:
2547
            // TRANSLATORS: popup menu item
2548
            // TRANSLATORS: remove player from ignore list
2549
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2550
            // TRANSLATORS: popup menu item
2551
            // TRANSLATORS: add player to disregarded list
2552
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2553
            // TRANSLATORS: popup menu item
2554
            // TRANSLATORS: add player to ignore list
2555
            mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2556
            // TRANSLATORS: popup menu item
2557
            // TRANSLATORS: add player to black list
2558
            mBrowserBox->addRow("/blacklist 'NAME'", _("Black list"));
2559
            // TRANSLATORS: popup menu item
2560
            // TRANSLATORS: add player to erased list
2561
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2562
            break;
2563
2564
        case Relation::ERASED:
2565
            // TRANSLATORS: popup menu item
2566
            // TRANSLATORS: remove player from ignore list
2567
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2568
            // TRANSLATORS: popup menu item
2569
            // TRANSLATORS: add player to disregarded list
2570
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2571
            // TRANSLATORS: popup menu item
2572
            // TRANSLATORS: add player to ignore list
2573
            mBrowserBox->addRow("/ignore 'NAME'", _("Completely ignore"));
2574
            break;
2575
2576
        default:
2577
            break;
2578
    }
2579
}
2580
2581
void PopupMenu::addFollow()
2582
{
2583
    if (features.getBoolValue("allowFollow"))
2584
    {
2585
        // TRANSLATORS: popup menu item
2586
        mBrowserBox->addRow("/follow 'NAME'", _("Follow"));
2587
    }
2588
    // TRANSLATORS: popup menu item
2589
    // TRANSLATORS: imitate player
2590
    mBrowserBox->addRow("/imitation 'NAME'", _("Imitate"));
2591
}
2592
2593
void PopupMenu::addBuySell(const Being *const being)
2594
{
2595
    if ((playerRelations.getDefault() & PlayerRelation::TRADE) != 0u)
2596
    {
2597
        mBrowserBox->addSeparator("##3---");
2598
        const bool haveVending =
2599
            (Net::getNetworkType() != ServerType::TMWATHENA);
2600
        if (being->isSellShopEnabled())
2601
        {
2602
            // TRANSLATORS: popup menu item
2603
            // TRANSLATORS: buy item
2604
            mBrowserBox->addRow("/buy 'NAME'", _("Buy"));
2605
        }
2606
        else if (!haveVending)
2607
        {
2608
            // TRANSLATORS: popup menu item
2609
            // TRANSLATORS: buy item
2610
            mBrowserBox->addRow("/buy 'NAME'", _("Buy (?)"));
2611
        }
2612
        if (being->isBuyShopEnabled())
2613
        {
2614
            // TRANSLATORS: popup menu item
2615
            // TRANSLATORS: sell item
2616
            mBrowserBox->addRow("/sell 'NAME'", _("Sell"));
2617
        }
2618
        else if (!haveVending)
2619
        {
2620
            // TRANSLATORS: popup menu item
2621
            // TRANSLATORS: sell item
2622
            mBrowserBox->addRow("/sell 'NAME'", _("Sell (?)"));
2623
        }
2624
    }
2625
}
2626
2627
void PopupMenu::addBuySellDefault()
2628
{
2629
    if ((playerRelations.getDefault() & PlayerRelation::TRADE) != 0u)
2630
    {
2631
        mBrowserBox->addSeparator("##3---");
2632
        // TRANSLATORS: popup menu item
2633
        // TRANSLATORS: buy item
2634
        mBrowserBox->addRow("/buy 'NAME'", _("Buy (?)"));
2635
        // TRANSLATORS: popup menu item
2636
        // TRANSLATORS: sell item
2637
        mBrowserBox->addRow("/sell 'NAME'", _("Sell (?)"));
2638
    }
2639
}
2640
2641
void PopupMenu::addPartyName(const std::string &partyName)
2642
{
2643
    if (localPlayer->isInParty())
2644
    {
2645
        if (localPlayer->getParty() != nullptr)
2646
        {
2647
            if (localPlayer->getParty()->getName() != partyName)
2648
            {
2649
                // TRANSLATORS: popup menu item
2650
                // TRANSLATORS: invite player to party
2651
                mBrowserBox->addRow("/party 'NAME'", _("Invite to party"));
2652
            }
2653
            else
2654
            {
2655
                // TRANSLATORS: popup menu item
2656
                // TRANSLATORS: kick player from party
2657
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
2658
                showAdoptCommands();
2659
            }
2660
            mBrowserBox->addSeparator("##3---");
2661
        }
2662
    }
2663
}
2664
2665
void PopupMenu::addParty(const std::string &nick)
2666
{
2667
    if (localPlayer->isInParty())
2668
    {
2669
        const Party *const party = localPlayer->getParty();
2670
        if (party != nullptr)
2671
        {
2672
            if (!party->isMember(nick))
2673
            {
2674
                // TRANSLATORS: popup menu item
2675
                // TRANSLATORS: invite player to party
2676
                mBrowserBox->addRow("/party 'NAME'", _("Invite to party"));
2677
            }
2678
            else
2679
            {
2680
                // TRANSLATORS: popup menu item
2681
                // TRANSLATORS: kick player from party
2682
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
2683
                showAdoptCommands();
2684
            }
2685
            mBrowserBox->addSeparator("##3---");
2686
        }
2687
    }
2688
}
2689
2690
void PopupMenu::addChat(const Being *const being)
2691
{
2692
    if (being == nullptr)
2693
        return;
2694
    const ChatObject *const chat = being->getChat();
2695
    if (chat != nullptr)
2696
    {
2697
        mBrowserBox->addRow("join chat",
2698
            // TRANSLATORS: popup menu item
2699
            // TRANSLATORS: invite player to party
2700
            strprintf(_("Join chat %s"), chat->title.c_str()).c_str());
2701
        mBrowserBox->addSeparator("##3---");
2702
    }
2703
}
2704
2705
void PopupMenu::addPlayerMisc()
2706
{
2707
    // TRANSLATORS: popup menu item
2708
    mBrowserBox->addRow("/showitems :'BEINGID'", _("Show Items"));
2709
    // TRANSLATORS: popup menu item
2710
    // TRANSLATORS: undress player
2711
    mBrowserBox->addRow("/undress :'BEINGID'", _("Undress"));
2712
    // TRANSLATORS: popup menu item
2713
    // TRANSLATORS: add comment to player
2714
    mBrowserBox->addRow("addcomment", _("Add comment"));
2715
}
2716
2717
void PopupMenu::addPickupFilter(const std::string &name)
2718
{
2719
    if (actorManager->isInPickupList(name)
2720
        || actorManager->isInIgnorePickupList(name))
2721
    {
2722
        mBrowserBox->addRow("/removepickup 'NAME'",
2723
            // TRANSLATORS: popup menu item
2724
            // TRANSLATORS: remove item from pickup list
2725
            _("Remove from pickup list"));
2726
    }
2727
    else
2728
    {
2729
        mBrowserBox->addRow("/addpickup 'NAME'",
2730
            // TRANSLATORS: popup menu item
2731
            // TRANSLATORS: popup menu item
2732
            _("Add to pickup list"));
2733
        mBrowserBox->addRow("/ignorepickup 'NAME'",
2734
            // TRANSLATORS: popup menu item
2735
            // TRANSLATORS: add item to pickup list
2736
            _("Add to ignore list"));
2737
    }
2738
}
2739
2740
void PopupMenu::showPopup(const int x, const int y,
2741
                          ListModel *const model)
2742
{
2743
    if (model == nullptr)
2744
        return;
2745
2746
    mBrowserBox->clearRows();
2747
    for (int f = 0, sz = model->getNumberOfElements(); f < sz; f ++)
2748
    {
2749
        mBrowserBox->addRow(strprintf("dropdown_%d", f),
2750
            model->getElementAt(f).c_str());
2751
    }
2752
    // TRANSLATORS: popup menu item
2753
    // TRANSLATORS: close menu
2754
    mBrowserBox->addRow("cancel", _("Cancel"));
2755
    showPopup(x, y);
2756
}
2757
2758
void PopupMenu::clear()
2759
{
2760
    if (mDialog != nullptr)
2761
    {
2762
        mDialog->close();
2763
        mDialog = nullptr;
2764
    }
2765
    mItemIndex = -1;
2766
    mItemId = 0;
2767
    for (int f = 0; f < maxCards; f ++)
2768
        mItemCards[f] = 0;
2769
    mMapItem = nullptr;
2770
    mTab = nullptr;
2771
    mSpell = nullptr;
2772
    mCallerWindow = nullptr;
2773
    mButton = nullptr;
2774
    mTextField = nullptr;
2775
}
2776
2777
void PopupMenu::addProtection()
2778
{
2779
    if (PlayerInfo::isItemProtected(mItemId))
2780
    {
2781
        mBrowserBox->addSeparator("##3---");
2782
        // TRANSLATORS: popup menu item
2783
        // TRANSLATORS: remove protection from item
2784
        mBrowserBox->addRow("/unprotectitem 'ITEMID'", _("Unprotect item"));
2785
    }
2786
    else
2787
    {
2788
        if (mItemId < SPELL_MIN_ID)
2789
        {
2790
            mBrowserBox->addSeparator("##3---");
2791
            // TRANSLATORS: popup menu item
2792
            // TRANSLATORS: add protection to item
2793
            mBrowserBox->addRow("/protectitem 'ITEMID'", _("Protect item"));
2794
        }
2795
    }
2796
}
2797
2798
void PopupMenu::addUse(const Item *const item)
2799
{
2800
    const ItemInfo &info = item->getInfo();
2801
    const std::string &str = (item->isEquipment() == Equipm_true
2802
        && item->isEquipped() == Equipped_true)
2803
        ? info.getUseButton2() : info.getUseButton();
2804
2805
    if (str.empty())
2806
    {
2807
        // TRANSLATORS: popup menu item
2808
        mBrowserBox->addRow("/useinv 'INVINDEX'", _("Use"));
2809
    }
2810
    else
2811
    {
2812
        // TRANSLATORS: popup menu item
2813
        mBrowserBox->addRow("/useinv 'INVINDEX'", str.c_str());
2814
    }
2815
}
2816
2817
void PopupMenu::addItemMenu(const Item *const item,
2818
                            const InventoryTypeT type)
2819
{
2820
    const ItemInfo &info = item->getInfo();
2821
    const STD_VECTOR<ItemMenuItem> *menu = nullptr;
2822
    switch (type)
2823
    {
2824
        case InventoryType::Inventory:
2825
            menu = &info.getInventoryMenuConst();
2826
            break;
2827
        case InventoryType::Storage:
2828
            menu = &info.getStorageMenuConst();
2829
            break;
2830
        case InventoryType::Cart:
2831
            menu = &info.getCartMenuConst();
2832
            break;
2833
        case InventoryType::Trade:
2834
        case InventoryType::Npc:
2835
        case InventoryType::Vending:
2836
        case InventoryType::MailEdit:
2837
        case InventoryType::MailView:
2838
        case InventoryType::Craft:
2839
        case InventoryType::TypeEnd:
2840
        default:
2841
            return;
2842
    }
2843
2844
    const bool firstMode = (item->isEquipment() == Equipm_true ?
2845
        (item->isEquipped() != Equipped_true) : (item->getQuantity() == 1));
2846
2847
    FOR_EACHP (STD_VECTOR<ItemMenuItem>::const_iterator, it, menu)
2848
    {
2849
        const ItemMenuItem &menuItem = *it;
2850
        const std::string &name = firstMode ?
2851
            menuItem.name1 : menuItem.name2;
2852
        const std::string &command = firstMode ?
2853
            menuItem.command1 : menuItem.command2;
2854
        if (command.empty() ||
2855
            name.empty())
2856
        {
2857
            continue;
2858
        }
2859
        mBrowserBox->addRow("/" + command, name.c_str());
2860
    }
2861
    mBrowserBox->addSeparator("##3---");
2862
}
2863
2864
void PopupMenu::addDrop(const Item *const item,
2865
                        const bool isProtected)
2866
{
2867
    if (!isProtected)
2868
    {
2869
        mBrowserBox->addSeparator("##3---");
2870
        if (item->getQuantity() > 1)
2871
        {
2872
            // TRANSLATORS: popup menu item
2873
            // TRANSLATORS: drop item
2874
            mBrowserBox->addRow("/dropinv 'INVINDEX'", _("Drop..."));
2875
            // TRANSLATORS: popup menu item
2876
            // TRANSLATORS: drop all item amount
2877
            mBrowserBox->addRow("/dropinvall 'INVINDEX'", _("Drop all"));
2878
        }
2879
        else
2880
        {
2881
            // TRANSLATORS: popup menu item
2882
            // TRANSLATORS: drop item
2883
            mBrowserBox->addRow("/dropinv 'INVINDEX'", _("Drop"));
2884
        }
2885
    }
2886
}
2887
2888
void PopupMenu::addGmCommands()
2889
{
2890
    if (localPlayer->isGM())
2891
    {
2892
        // TRANSLATORS: popup menu item
2893
        // TRANSLATORS: gm commands
2894
        mBrowserBox->addRow("gm", _("GM..."));
2895
    }
2896
}
2897
2898
void PopupMenu::showPlayerMenu()
2899
{
2900
    mBrowserBox->clearRows();
2901
    // TRANSLATORS: popup menu header
2902
    mBrowserBox->addRow(strprintf(_("Show %s"),
2903
        mName.c_str()),
2904
        false);
2905
    if (isAllowCommand(ServerCommandType::accinfo))
2906
    {
2907
        // TRANSLATORS: popup menu item
2908
        // TRANSLATORS: show player account info
2909
        mBrowserBox->addRow("/showaccountinfo 'NAME'", _("Account info"));
2910
    }
2911
    if (isAllowOtherCommand(ServerCommandType::exp))
2912
    {
2913
        // TRANSLATORS: popup menu item
2914
        // TRANSLATORS: show player level
2915
        mBrowserBox->addRow("/showlevel 'NAME'", _("Level"));
2916
    }
2917
    if (isAllowOtherCommand(ServerCommandType::stats))
2918
    {
2919
        // TRANSLATORS: popup menu item
2920
        // TRANSLATORS: show player stats
2921
        mBrowserBox->addRow("/showstats 'NAME'", _("Stats"));
2922
    }
2923
    if (isAllowOtherCommand(ServerCommandType::itemlist))
2924
    {
2925
        // TRANSLATORS: popup menu item
2926
        // TRANSLATORS: show player inventory list
2927
        mBrowserBox->addRow("/showinventory 'NAME'", _("Inventory"));
2928
    }
2929
    if (isAllowOtherCommand(ServerCommandType::storagelist))
2930
    {
2931
        // TRANSLATORS: popup menu item
2932
        // TRANSLATORS: show player storage list
2933
        mBrowserBox->addRow("/showstorage 'NAME'", _("Storage"));
2934
    }
2935
    if (isAllowOtherCommand(ServerCommandType::cartlist))
2936
    {
2937
        // TRANSLATORS: popup menu item
2938
        // TRANSLATORS: show player cart list
2939
        mBrowserBox->addRow("/showcart 'NAME'", _("Cart"));
2940
    }
2941
    if (isAllowOtherCommand(ServerCommandType::commands))
2942
    {
2943
        // TRANSLATORS: popup menu item
2944
        // TRANSLATORS: gm commands
2945
        mBrowserBox->addRow("/gmcommands 'NAME'", _("Commands"));
2946
    }
2947
    if (isAllowOtherCommand(ServerCommandType::charcommands))
2948
    {
2949
        // TRANSLATORS: popup menu item
2950
        // TRANSLATORS: gm char commands
2951
        mBrowserBox->addRow("/gmcharcommands 'NAME'", _("Char commands"));
2952
    }
2953
    // TRANSLATORS: popup menu item
2954
    // TRANSLATORS: back to gm menu
2955
    mBrowserBox->addRow("gm", _("Back"));
2956
    // TRANSLATORS: popup menu item
2957
    // TRANSLATORS: close menu
2958
    mBrowserBox->addRow("cancel", _("Cancel"));
2959
    showPopup(getX(), getY());
2960
}
2961
2962
void PopupMenu::showPlayerGMCommands(const std::string &name)
2963
{
2964
    if (localPlayer == nullptr)
2965
        return;
2966
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
2967
    if (!legacy && isAllowCommand(ServerCommandType::where))
2968
    {
2969
        // TRANSLATORS: popup menu item
2970
        // TRANSLATORS: find player position
2971
        mBrowserBox->addRow("/locateplayer 'NAME'", _("Locate"));
2972
    }
2973
    if (legacy)
2974
    {
2975
        // TRANSLATORS: popup menu item
2976
        // TRANSLATORS: check player ip
2977
        mBrowserBox->addRow("/ipcheck 'NAME'", _("Check ip"));
2978
    }
2979
    if (isAllowCommand(ServerCommandType::jumpto))
2980
    {
2981
        // TRANSLATORS: popup menu item
2982
        // TRANSLATORS: go to player position
2983
        mBrowserBox->addRow("/gotopc 'NAME'", _("Goto"));
2984
    }
2985
    if (isAllowCommand(ServerCommandType::recall))
2986
    {
2987
        // TRANSLATORS: popup menu item
2988
        // TRANSLATORS: recall player to current position
2989
        mBrowserBox->addRow("/recallpc 'NAME'", _("Recall"));
2990
    }
2991
    if (isAllowOtherCommand(ServerCommandType::alive))
2992
    {
2993
        // TRANSLATORS: popup menu item
2994
        // TRANSLATORS: revive player
2995
        mBrowserBox->addRow("/alive 'NAME'", _("Revive"));
2996
    }
2997
    if (!legacy)
2998
    {
2999
        Being *const being = actorManager->findBeingByName(name,
3000
            ActorType::Player);
3001
        if (being != nullptr && being == localPlayer)
3002
        {
3003
            if (!being->getPartyName().empty() &&
3004
                isAllowCommand(ServerCommandType::partyrecall))
3005
            {
3006
                mBrowserBox->addRow("/partyrecall 'PARTY'",
3007
                    // TRANSLATORS: popup menu item
3008
                    // TRANSLATORS: recall all party members to player location
3009
                    _("Recall party"));
3010
            }
3011
            if (!being->getGuildName().empty() &&
3012
                isAllowCommand(ServerCommandType::guildrecall))
3013
            {
3014
                mBrowserBox->addRow("/guildrecall 'PARTY'",
3015
                    // TRANSLATORS: popup menu item
3016
                    // TRANSLATORS: recall all guild members to player location
3017
                    _("Recall guild"));
3018
            }
3019
        }
3020
        if (localPlayer->isInParty())
3021
        {
3022
            const Party *const party = localPlayer->getParty();
3023
            if (party != nullptr &&
3024
                party->isMember(name) &&
3025
                isAllowCommand(ServerCommandType::changeleader))
3026
            {
3027
                mBrowserBox->addRow("/gmpartyleader 'NAME'",
3028
                    // TRANSLATORS: popup menu item
3029
                    // TRANSLATORS: give party leader status
3030
                    _("Give party leader"));
3031
            }
3032
        }
3033
3034
        if (isAllowCommand(ServerCommandType::nuke))
3035
        {
3036
            // TRANSLATORS: popup menu item
3037
            // TRANSLATORS: nuke player
3038
            mBrowserBox->addRow("/gmnuke 'NAME'", _("Nuke"));
3039
        }
3040
        if (isAllowOtherCommand(ServerCommandType::kill))
3041
        {
3042
            // TRANSLATORS: popup menu item
3043
            // TRANSLATORS: kill player
3044
            mBrowserBox->addRow("/kill 'NAME'", _("Kill"));
3045
        }
3046
        if (mBeingId != BeingId_zero)
3047
        {
3048
            mBrowserBox->addSeparator("##3---");
3049
            // TRANSLATORS: popup menu item
3050
            // TRANSLATORS: show menu
3051
            mBrowserBox->addRow("show", _("Show..."));
3052
            // TRANSLATORS: popup menu item
3053
            // TRANSLATORS: mute menu
3054
            mBrowserBox->addRow("mute", _("Mute..."));
3055
        }
3056
    }
3057
    if (legacy)
3058
    {
3059
        if (localPlayer->getName() == mName)
3060
        {
3061
            // TRANSLATORS: popup menu item
3062
            // TRANSLATORS: hide player
3063
            mBrowserBox->addRow("/hide", _("Hide"));
3064
            mBrowserBox->addSeparator("##3---");
3065
        }
3066
    }
3067
    else
3068
    {
3069
        if (isAllowOtherCommand(ServerCommandType::heal))
3070
        {
3071
            // TRANSLATORS: popup menu item
3072
            // TRANSLATORS: heal player
3073
            mBrowserBox->addRow("/gmheal 'NAME'", _("Heal"));
3074
        }
3075
        if (isAllowOtherCommand(ServerCommandType::monsterignore))
3076
        {
3077
            // TRANSLATORS: popup menu item
3078
            // TRANSLATORS: enable immortal mode for player
3079
            mBrowserBox->addRow("/immortal 'NAME'", _("Immortal"));
3080
        }
3081
        if (isAllowCommand(ServerCommandType::jail))
3082
        {
3083
            // TRANSLATORS: popup menu item
3084
            // TRANSLATORS: send player to jail
3085
            mBrowserBox->addRow("/jail 'NAME'", _("Jail"));
3086
        }
3087
        if (isAllowCommand(ServerCommandType::unjail))
3088
        {
3089
            // TRANSLATORS: popup menu item
3090
            // TRANSLATORS: restore player from jail
3091
            mBrowserBox->addRow("/unjail 'NAME'", _("Unjail"));
3092
        }
3093
        if (name == localPlayer->getName() &&
3094
            isAllowCommand(ServerCommandType::hide))
3095
        {
3096
            // TRANSLATORS: popup menu item
3097
            // TRANSLATORS: hide player
3098
            mBrowserBox->addRow("/hide 'NAME'", _("Hide"));
3099
        }
3100
        mBrowserBox->addSeparator("##3---");
3101
        if (isAllowOtherCommand(ServerCommandType::killer))
3102
        {
3103
            // TRANSLATORS: popup menu item
3104
            // TRANSLATORS: set player as killer
3105
            mBrowserBox->addRow("/killer 'NAME'", _("Killer"));
3106
        }
3107
        if (isAllowOtherCommand(ServerCommandType::killable))
3108
        {
3109
            // TRANSLATORS: popup menu item
3110
            // TRANSLATORS: set player as killable
3111
            mBrowserBox->addRow("/killable 'NAME'", _("Killable"));
3112
        }
3113
        if (isAllowOtherCommand(ServerCommandType::save))
3114
        {
3115
            // TRANSLATORS: popup menu item
3116
            // TRANSLATORS: set player save position
3117
            mBrowserBox->addRow("/savepos 'NAME'", _("Set save"));
3118
        }
3119
        if (isAllowOtherCommand(ServerCommandType::load))
3120
        {
3121
            // TRANSLATORS: popup menu item
3122
            // TRANSLATORS: warp player to save position
3123
            mBrowserBox->addRow("/loadpos 'NAME'", _("Warp to save"));
3124
        }
3125
        if (isAllowOtherCommand(ServerCommandType::jump))
3126
        {
3127
            // TRANSLATORS: popup menu item
3128
            // TRANSLATORS: warp player to random position on same map
3129
            mBrowserBox->addRow("/randomwarp 'NAME'", _("Warp to random"));
3130
        }
3131
        mBrowserBox->addSeparator("##3---");
3132
        if (isAllowCommand(ServerCommandType::clone))
3133
        {
3134
            // TRANSLATORS: popup menu item
3135
            // TRANSLATORS: spawn player clone
3136
            mBrowserBox->addRow("/spawnclone 'NAME'", _("Spawn clone"));
3137
        }
3138
        if (isAllowCommand(ServerCommandType::slaveclone))
3139
        {
3140
            mBrowserBox->addRow("/spawnslaveclone 'NAME'",
3141
                // TRANSLATORS: popup menu item
3142
                // TRANSLATORS: spawn slave player clone
3143
                _("Spawn slave clone"));
3144
        }
3145
        if (isAllowCommand(ServerCommandType::evilclone))
3146
        {
3147
            mBrowserBox->addRow("/spawnevilclone 'NAME'",
3148
                // TRANSLATORS: popup menu item
3149
                // TRANSLATORS: spawn evil player clone
3150
                _("Spawn evil clone"));
3151
        }
3152
        mBrowserBox->addSeparator("##3---");
3153
        if (isAllowOtherCommand(ServerCommandType::breakguild))
3154
        {
3155
            // TRANSLATORS: popup menu item
3156
            // TRANSLATORS: break guild
3157
            mBrowserBox->addRow("/gmbreakguild 'NAME'", _("Break guild"));
3158
        }
3159
    }
3160
    if (mBeingId != BeingId_zero &&
3161
        isAllowCommand(ServerCommandType::kick))
3162
    {
3163
        mBrowserBox->addSeparator("##3---");
3164
        // TRANSLATORS: popup menu item
3165
        // TRANSLATORS: kick player
3166
        mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3167
    }
3168
}
3169
3170
void PopupMenu::showMuteCommands()
3171
{
3172
    mBrowserBox->clearRows();
3173
    // TRANSLATORS: popup menu header
3174
    mBrowserBox->addRow(strprintf(_("Mute %s"),
3175
        mName.c_str()),
3176
        false);
3177
    if (mBeingId != BeingId_zero &&
3178
        Net::getNetworkType() != ServerType::TMWATHENA &&
3179
        isAllowCommand(ServerCommandType::mute))
3180
    {
3181
        mBrowserBox->addRow("mute_+1",
3182
            // TRANSLATORS: popup menu item
3183
            // TRANSLATORS: mute player
3184
            strprintf(_("Mute %d"), 1).c_str());
3185
        mBrowserBox->addRow("mute_+5",
3186
            // TRANSLATORS: popup menu item
3187
            // TRANSLATORS: mute player
3188
            strprintf(_("Mute %d"), 5).c_str());
3189
        mBrowserBox->addRow("mute_+10",
3190
            // TRANSLATORS: popup menu item
3191
            // TRANSLATORS: mute player
3192
            strprintf(_("Mute %d"), 10).c_str());
3193
        mBrowserBox->addRow("mute_+15",
3194
            // TRANSLATORS: popup menu item
3195
            // TRANSLATORS: mute player
3196
            strprintf(_("Mute %d"), 15).c_str());
3197
        mBrowserBox->addRow("mute_+30",
3198
            // TRANSLATORS: popup menu item
3199
            // TRANSLATORS: mute player
3200
            strprintf(_("Mute %d"), 30).c_str());
3201
3202
        mBrowserBox->addRow("mute_-1",
3203
            // TRANSLATORS: popup menu item
3204
            // TRANSLATORS: mute player
3205
            strprintf(_("Unmute %d"), 1).c_str());
3206
        mBrowserBox->addRow("mute_-5",
3207
            // TRANSLATORS: popup menu item
3208
            // TRANSLATORS: mute player
3209
            strprintf(_("Unmute %d"), 5).c_str());
3210
        mBrowserBox->addRow("mute_-10",
3211
            // TRANSLATORS: popup menu item
3212
            // TRANSLATORS: mute player
3213
            strprintf(_("Unmute %d"), 10).c_str());
3214
        mBrowserBox->addRow("mute_-15",
3215
            // TRANSLATORS: popup menu item
3216
            // TRANSLATORS: mute player
3217
            strprintf(_("Unmute %d"), 15).c_str());
3218
        mBrowserBox->addRow("mute_-30",
3219
            // TRANSLATORS: popup menu item
3220
            // TRANSLATORS: mute player
3221
            strprintf(_("Unmute %d"), 30).c_str());
3222
        mBrowserBox->addSeparator("##3---");
3223
    }
3224
    // TRANSLATORS: popup menu item
3225
    // TRANSLATORS: back to gm menu
3226
    mBrowserBox->addRow("gm", _("Back"));
3227
    // TRANSLATORS: popup menu item
3228
    // TRANSLATORS: close menu
3229
    mBrowserBox->addRow("cancel", _("Cancel"));
3230
    showPopup(getX(), getY());
3231
}
3232
3233
void PopupMenu::showNpcGMCommands()
3234
{
3235
    if (mBeingId != BeingId_zero)
3236
    {
3237
        if (isAllowCommand(ServerCommandType::kick))
3238
        {
3239
            // TRANSLATORS: popup menu item
3240
            // TRANSLATORS: kick player
3241
            mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3242
        }
3243
        const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3244
        if (!legacy)
3245
        {
3246
            if (isAllowCommand(ServerCommandType::hidenpc))
3247
            {
3248
                // TRANSLATORS: popup menu item
3249
                // TRANSLATORS: hide npc
3250
                mBrowserBox->addRow("/hidenpc 'EXTNAME'", _("Hide"));
3251
            }
3252
            mBrowserBox->addSeparator("##3---");
3253
            if (isAllowCommand(ServerCommandType::npcmove))
3254
            {
3255
                mBrowserBox->addRow("/npcmove 'EEXTNAME' 'PLAYERX' 'PLAYERY'",
3256
                    // TRANSLATORS: popup menu item
3257
                    // TRANSLATORS: warp npc to player location
3258
                    _("Recall"));
3259
            }
3260
            if (isAllowCommand(ServerCommandType::disguise))
3261
            {
3262
                mBrowserBox->addRow("/disguise 'BEINGSUBTYPEID'",
3263
                    // TRANSLATORS: popup menu item
3264
                    // TRANSLATORS: disguise to npc
3265
                    _("Disguise"));
3266
            }
3267
            if (isAllowCommand(ServerCommandType::tonpc))
3268
            {
3269
                // TRANSLATORS: popup menu item
3270
                // TRANSLATORS: warp to npc
3271
                mBrowserBox->addRow("/gotonpc 'EXTNAME'", _("Goto"));
3272
            }
3273
        }
3274
    }
3275
}
3276
3277
void PopupMenu::showMonsterGMCommands()
3278
{
3279
    if (mBeingId != BeingId_zero)
3280
    {
3281
        const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3282
        if (isAllowCommand(ServerCommandType::kick))
3283
        {
3284
            // TRANSLATORS: popup menu item
3285
            // TRANSLATORS: kick monster
3286
            mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3287
        }
3288
        if (isAllowCommand(ServerCommandType::monster))
3289
        {
3290
            // TRANSLATORS: popup menu item
3291
            // TRANSLATORS: spawn monster
3292
            mBrowserBox->addRow("/spawn 'BEINGSUBTYPEID'", _("Spawn same"));
3293
        }
3294
        if (!legacy)
3295
        {
3296
            if (isAllowCommand(ServerCommandType::summon))
3297
            {
3298
                mBrowserBox->addRow("/spawnslave 'BEINGSUBTYPEID'",
3299
                    // TRANSLATORS: popup menu item
3300
                    // TRANSLATORS: spawn slave monster
3301
                    _("Spawn slave"));
3302
            }
3303
            if (isAllowCommand(ServerCommandType::disguise))
3304
            {
3305
                mBrowserBox->addRow("/disguise 'BEINGSUBTYPEID'",
3306
                    // TRANSLATORS: popup menu item
3307
                    // TRANSLATORS: disguise to monster
3308
                    _("Disguise"));
3309
            }
3310
            mBrowserBox->addSeparator("##3---");
3311
            if (isAllowCommand(ServerCommandType::mobinfo))
3312
            {
3313
                mBrowserBox->addRow("/monsterinfo 'BEINGSUBTYPEID'",
3314
                    // TRANSLATORS: popup menu item
3315
                    // TRANSLATORS: show monster information
3316
                    _("Info"));
3317
            }
3318
            if (isAllowCommand(ServerCommandType::mobsearch))
3319
            {
3320
                mBrowserBox->addRow("/mobsearch 'BEINGSUBTYPEID'",
3321
                    // TRANSLATORS: popup menu item
3322
                    // TRANSLATORS: show selected monster in current map
3323
                    _("Search"));
3324
            }
3325
            if (isAllowCommand(ServerCommandType::whereis))
3326
            {
3327
                mBrowserBox->addRow("/mobspawnsearch 'BEINGSUBTYPEID'",
3328
                    // TRANSLATORS: popup menu item
3329
                    // TRANSLATORS: show selected monster spawns in all maps
3330
                    _("Search spawns"));
3331
            }
3332
        }
3333
    }
3334
}
3335
3336
void PopupMenu::showFloorItemGMCommands()
3337
{
3338
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3339
    if (legacy)
3340
        return;
3341
    if (isAllowCommand(ServerCommandType::iteminfo))
3342
    {
3343
        // TRANSLATORS: popup menu item
3344
        // TRANSLATORS: show item information
3345
        mBrowserBox->addRow("/iteminfo 'ITEMID'", _("Info"));
3346
    }
3347
    if (isAllowCommand(ServerCommandType::whodrops))
3348
    {
3349
        // TRANSLATORS: popup menu item
3350
        // TRANSLATORS: show who drops item
3351
        mBrowserBox->addRow("/whodrops 'ITEMID'", _("Who drops"));
3352
    }
3353
}
3354
3355
void PopupMenu::showItemGMCommands()
3356
{
3357
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3358
    if (legacy)
3359
        return;
3360
    if (isAllowCommand(ServerCommandType::iteminfo))
3361
    {
3362
        // TRANSLATORS: popup menu item
3363
        // TRANSLATORS: show item information
3364
        mBrowserBox->addRow("/iteminfo 'ITEMID'", _("Info"));
3365
    }
3366
    if (isAllowCommand(ServerCommandType::whodrops))
3367
    {
3368
        // TRANSLATORS: popup menu item
3369
        // TRANSLATORS: show who drops item
3370
        mBrowserBox->addRow("/whodrops 'ITEMID'", _("Who drops"));
3371
    }
3372
    mBrowserBox->addSeparator("##3---");
3373
    if (isAllowCommand(ServerCommandType::item))
3374
    {
3375
        // TRANSLATORS: popup menu item
3376
        // TRANSLATORS: gm create item
3377
        mBrowserBox->addRow("/createitem 'ITEMID' 1", _("Add 1"));
3378
        // TRANSLATORS: popup menu item
3379
        // TRANSLATORS: gm create item
3380
        mBrowserBox->addRow("/createitem 'ITEMID' 5", _("Add 5"));
3381
        // TRANSLATORS: popup menu item
3382
        // TRANSLATORS: gm create item
3383
        mBrowserBox->addRow("/createitem 'ITEMID' 10", _("Add 10"));
3384
        // TRANSLATORS: popup menu item
3385
        // TRANSLATORS: gm create item
3386
        mBrowserBox->addRow("/createitem 'ITEMID' 100", _("Add 100"));
3387
        // TRANSLATORS: popup menu item
3388
        // TRANSLATORS: gm create item
3389
        mBrowserBox->addRow("/createitem 'ITEMID' 1000", _("Add 1000"));
3390
        // TRANSLATORS: popup menu item
3391
        // TRANSLATORS: gm create item
3392
        mBrowserBox->addRow("/createitem 'ITEMID' 10000", _("Add 10000"));
3393
    }
3394
}
3395
3396
void PopupMenu::showGMPopup(const std::string &name)
3397
{
3398
    mBrowserBox->clearRows();
3399
    // TRANSLATORS: popup menu header
3400
    mBrowserBox->addRow(_("GM commands"), false);
3401
    if (localPlayer->isGM())
3402
    {
3403
        switch (mType)
3404
        {
3405
            case ActorType::Player:
3406
                showPlayerGMCommands(name);
3407
                break;
3408
            case ActorType::Npc:
3409
                showNpcGMCommands();
3410
                break;
3411
            case ActorType::Monster:
3412
                showMonsterGMCommands();
3413
                break;
3414
            case ActorType::FloorItem:
3415
                showFloorItemGMCommands();
3416
                break;
3417
            case ActorType::Homunculus:
3418
                showHomunGMCommands();
3419
                break;
3420
            case ActorType::Pet:
3421
                showPetGMCommands();
3422
                break;
3423
            case ActorType::Mercenary:
3424
                showMercenaryGMCommands();
3425
                break;
3426
            case ActorType::SkillUnit:
3427
                break;
3428
            default:
3429
            case ActorType::Unknown:
3430
                if (mItemId != 0)
3431
                    showItemGMCommands();
3432
                break;
3433
            case ActorType::Portal:
3434
            case ActorType::Avatar:
3435
            case ActorType::Elemental:
3436
                break;
3437
        }
3438
    }
3439
3440
    mBrowserBox->addSeparator("##3---");
3441
    // TRANSLATORS: popup menu item
3442
    // TRANSLATORS: close menu
3443
    mBrowserBox->addRow("cancel", _("Cancel"));
3444
3445
    showPopup(getX(), getY());
3446
}
3447
3448
void PopupMenu::showHomunGMCommands()
3449
{
3450
}
3451
3452
void PopupMenu::showPetGMCommands()
3453
{
3454
}
3455
3456
void PopupMenu::showMercenaryGMCommands()
3457
{
3458
}
3459
3460
void PopupMenu::showCraftPopup()
3461
{
3462
    mBrowserBox->clearRows();
3463
3464
    for (int f = 0; f < 9; f ++)
3465
    {
3466
        const std::string cmd = strprintf("/craft %d", f);
3467
        mBrowserBox->addRow(cmd,
3468
            // TRANSLATORS: popup menu item
3469
            // TRANSLATORS: move current item to craft slot
3470
            strprintf(_("Move to craft %d"), f + 1).c_str());
3471
    }
3472
3473
    // TRANSLATORS: popup menu item
3474
    // TRANSLATORS: close menu
3475
    mBrowserBox->addRow("cancel", _("Cancel"));
3476
3477
    showPopup(mX, mY);
3478
}
3479
3480
void PopupMenu::addMailCommands()
3481
{
3482
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3483
        return;
3484
3485
    // TRANSLATORS: popup menu item
3486
    // TRANSLATORS: open mail dialog
3487
    mBrowserBox->addRow("/mailto 'NAME'", _("Mail to..."));
3488
}
3489
3490
void PopupMenu::addCatchPetCommands()
3491
{
3492
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3493
        return;
3494
    // TRANSLATORS: popup menu item
3495
    // TRANSLATORS: catch pet command
3496
    mBrowserBox->addRow("/catchpet :'BEINGID'", _("Taming pet"));
3497
}
3498
3499
void PopupMenu::showAdoptCommands()
3500
{
3501
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3502
        return;
3503
    // TRANSLATORS: popup menu item
3504
    // TRANSLATORS: adopt child command
3505
    mBrowserBox->addRow("/adoptchild 'NAME'", _("Adopt child"));
3506
}
3507
3508
void PopupMenu::addSocialMenu()
3509
{
3510
    initPopup();
3511
    mBrowserBox->clearRows();
3512
    setMousePos();
3513
    const Party *const party = localPlayer->getParty();
3514
    if (party != nullptr)
3515
    {
3516
        // TRANSLATORS: popup menu item
3517
        // TRANSLATORS: leave party
3518
        mBrowserBox->addRow("/leaveparty", _("Leave party"));
3519
    }
3520
    else
3521
    {
3522
        // TRANSLATORS: popup menu item
3523
        // TRANSLATORS: create party
3524
        mBrowserBox->addRow("/createparty", _("Create party"));
3525
    }
3526
3527
    if (Net::getNetworkType() != ServerType::TMWATHENA)
3528
    {
3529
        const Guild *const guild = localPlayer->getGuild();
3530
        if (guild != nullptr)
3531
        {
3532
            // TRANSLATORS: popup menu item
3533
            // TRANSLATORS: leave guild
3534
            mBrowserBox->addRow("/leaveguild", _("Leave guild"));
3535
        }
3536
        else
3537
        {
3538
            // TRANSLATORS: popup menu item
3539
            // TRANSLATORS: create guild
3540
            mBrowserBox->addRow("/createguild", _("Create guild"));
3541
        }
3542
    }
3543
    mBrowserBox->addSeparator("##3---");
3544
}
3545
3546
void PopupMenu::showPartyPopup()
3547
{
3548
    addSocialMenu();
3549
3550
    // TRANSLATORS: popup menu item
3551
    // TRANSLATORS: close menu
3552
    mBrowserBox->addRow("cancel", _("Cancel"));
3553
    showPopup(mX, mY);
3554
}
3555
3556
void PopupMenu::showGuildPopup()
3557
{
3558
    addSocialMenu();
3559
3560
    // TRANSLATORS: popup menu item
3561
    // TRANSLATORS: change guild notice message
3562
    mBrowserBox->addRow("/guildnotice", _("Change notice"));
3563
3564
    // TRANSLATORS: popup menu item
3565
    // TRANSLATORS: close menu
3566
    mBrowserBox->addRow("cancel", _("Cancel"));
3567
    showPopup(mX, mY);
3568
}
3569
3570
void PopupMenu::showAttackPopup()
3571
{
3572
    addSocialMenu();
3573
3574
    // TRANSLATORS: popup menu item
3575
    // TRANSLATORS: close menu
3576
    mBrowserBox->addRow("cancel", _("Cancel"));
3577
    showPopup(mX, mY);
3578
}
3579
3580
void PopupMenu::showNavigationPopup()
3581
{
3582
    addSocialMenu();
3583
3584
    // TRANSLATORS: popup menu item
3585
    // TRANSLATORS: close menu
3586
    mBrowserBox->addRow("cancel", _("Cancel"));
3587
    showPopup(mX, mY);
3588
}
3589
3590
void PopupMenu::showPickupPopup()
3591
{
3592
    addSocialMenu();
3593
3594
    // TRANSLATORS: popup menu item
3595
    // TRANSLATORS: close menu
3596
    mBrowserBox->addRow("cancel", _("Cancel"));
3597
    showPopup(mX, mY);
3598
}
3599
3600
void PopupMenu::showPlayersPopup()
3601
{
3602
    addSocialMenu();
3603
3604
    // TRANSLATORS: popup menu item
3605
    // TRANSLATORS: close menu
3606
    mBrowserBox->addRow("cancel", _("Cancel"));
3607
    showPopup(mX, mY);
3608
}
3609
3610
void PopupMenu::showFriendsPopup()
3611
{
3612
    addSocialMenu();
3613
3614
    // TRANSLATORS: popup menu item
3615
    // TRANSLATORS: close menu
3616
    mBrowserBox->addRow("cancel", _("Cancel"));
3617
    showPopup(mX, mY);
3618
}
3619
3620
void PopupMenu::moveUp()
3621
{
3622
    mBrowserBox->moveSelectionUp();
3623
}
3624
3625
void PopupMenu::moveDown()
3626
{
3627
    mBrowserBox->moveSelectionDown();
3628
}
3629
3630
void PopupMenu::select()
3631
{
3632
    mBrowserBox->selectSelection();
3633

3
}